Forum: Mikrocontroller und Digitale Elektronik attiny13 problem mit timer0


von Florian T. (florian_t)


Lesenswert?

Hallo zusammen,
ich versuche den timer0 beim tiny13 zu verwenden. Der Timer scheint aber 
nicht zu laufen, denn der code in der ISR wird nicht ausgeführt.

Ich initialisiere den Timer so:
im Main()
1
TIMSK0 = (1<<TOIE0); // enable timer overflow interrupt for both Timer0
2
TCNT0 = 0x00; // set timer0 counter initial value to 0
3
TCCR0B = (1<<CS02) | (1<<CS00); // start timer0 with /1024 prescaler
4
5
sei();
6
7
for(;;) {
8
    if(_main_counter == 1000) {
9
        PORTB |= 1 << PB4
10
    }
11
}

Die ISR
1
ISR(TIM0_OVF_vect) {
2
  _main_counter++;
3
}

Das Problem ist, dass der code in der IF-Bedingung nie ausgeführt wird.
Der Tiny13 läuft auf 9,6MHz und CKDIV8 ist ausgeschaltet.
Der Code läuft auch im Simulator nicht.
Hat jemand Anregungen für mich?

von Peter II (Gast)


Lesenswert?

ist _main_counter volatile?

von Cyblord -. (cyblord)


Lesenswert?

Peter II schrieb:
> ist _main_counter volatile?

Eben. Den entscheidenen Code-Teil wieder mal nicht gezeigt. Ist es so 
schwer den ganzen verdammten Code zu zeigen und nicht immer nur genau 
den Teil in dem Fehler nicht ist? Das ist so selten dämlich!

gruß cyblord

von Florian T. (florian_t)


Lesenswert?

cyblord ---- schrieb:
> Eben. Den entscheidenen Code-Teil wieder mal nicht gezeigt. Ist es so
> schwer den ganzen verdammten Code zu zeigen und nicht immer nur genau
> den Teil in dem Fehler nicht ist? Das ist so selten dämlich!
>
> gruß cyblord
1
volatile uint16_t _main_counter;

Sorry, vergessen zu erwähnen. Ja, alle Variablen die ich in den ISRs 
benutze sind volatile. Das Semikolon beim PortPin ändern habe ich nur 
hier vergessen, im code ist es vorhanden.

Das Problem ist: Ich mache im AVR Studio einen Breakpoint in die ISR und 
lasse das Ding im emulator laufen. Leider wird der Breakpoint nie 
angesprungen. In der Schaltung auf dem Steckbrett äußert sich das 
ebenso, da der Code der damit gesteuert wird nicht läuft.

Um es klar zu stellen: Der Code der ausgeführt werden soll, ist eine 
Serielle Übertragung. Ich messe mit dem Multimeter am entsprechenden Pin 
aber immer einen LOW Pegel. Die Übertragungsgeschwindigkeit ist langsam 
genug um beim Multimeter wenigstens eine Veränderung auslösen zu müssen, 
aber auch das ist nicht der Fall.

von Karl H. (kbuchegg)


Lesenswert?

Florian Trück schrieb:

> Sorry, vergessen zu erwähnen. Ja, alle Variablen die ich in den ISRs
> benutze sind volatile. Das Semikolon beim PortPin ändern habe ich nur
> hier vergessen, im code ist es vorhanden.

Bitte zeig deinen richtigen Code!
Häng einfach dein C-File hier als Attachment an.

Das ist für dich am einfachsten. Das ist für uns am einfachsten. Und wir 
haben tatsächlich dann 100% das Programm vor uns, welches auf deinem µC 
läuft (vorausgesetzt, dass du das richtige Hex-File gebrannt hast und 
das in der Entwicklungsumgebung auch wirklich ein Tiny13 eingestellt 
ist)

> Um es klar zu stellen: Der Code der ausgeführt werden soll, ist eine
> Serielle Übertragung. Ich messe mit dem Multimeter am entsprechenden Pin
> aber immer einen LOW Pegel. Die Übertragungsgeschwindigkeit ist langsam
> genug um beim Multimeter wenigstens eine Veränderung auslösen zu müssen,
> aber auch das ist nicht der Fall.

Tipp für die Zukunft.
An dieser Stelle ist eine simple LED das bessere Messinstrument. Denn 
eine LED siehst du auch dann noch flackern, wenn dein Voltmeter schon 
längst nur noch einen konstanten Wert anzeigt.

von Fred S. (kogitsune)


Lesenswert?

Unter Atmel Studio 6 läuft das bei mir problemlos (d.h. der Breakpoint 
in der ISR wird angesprungen!):
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <inttypes.h>
4
5
volatile uint16_t _main_counter;
6
7
int main () {
8
  TIMSK0 = (1<<TOIE0); // enable timer overflow interrupt for both Timer0
9
  TCNT0 = 0x00; // set timer0 counter initial value to 0
10
  TCCR0B = (1<<CS02) | (1<<CS00); // start timer0 with /1024 prescaler
11
12
  sei();
13
14
  for(;;) {
15
    if(_main_counter == 1000) {
16
      PORTB |= 1 << PB4;
17
    }
18
  }
19
}
20
21
22
ISR(TIM0_OVF_vect) {
23
  _main_counter++ ;
24
}

Anmerkungen:
1. Rechne nicht damit, dass sich an PB4 etwas ändert, denn Du setzt das 
DDRB nicht.
2. Der Vergleich
1
if (_main_counter == 1000)
 funktioniert hier zwar wegen des hohen Prescalerwerts, aber eigentlich 
müsste der Zugriff atomar sein!
3. Zeige uns Deinen GANZEN Code (wie oben schon mehrfach gesagt!).

von Florian T. (florian_t)


Angehängte Dateien:

Lesenswert?

Also gut, ok. Hier das C-File. Es war nicht mein Gedanke irgendwas 
geheim zu halten. Ich wollte mich nur nicht blamieren oder allzu herbe 
Kritik für für den Code einheimsen.

Ich hoffe ihr seht mehr als ich.
Bin mir nicht sicher ob ich F_CPU richtig definiert habe, aber das 
sollte für den Code erstmal uninteressant sein, da die ISR vom Timer 
davon ja erstmal nicht beeinflusst wird, oder?

von Stefan E. (sternst)


Lesenswert?

Florian Trück schrieb:
> Die Übertragungsgeschwindigkeit ist langsam
> genug um beim Multimeter wenigstens eine Veränderung auslösen zu müssen,
> aber auch das ist nicht der Fall.

Im Gegenteil, die Übertragungsgeschwindigkeit ist rasend schnell.
1
_delay_us( 16L / BAUD );
Oder welchen Delay erwartest du bei _delay_us(0) zu bekommen?

von Karl H. (kbuchegg)


Lesenswert?

Florian Trück schrieb:
> Also gut, ok. Hier das C-File. Es war nicht mein Gedanke irgendwas
> geheim zu halten. Ich wollte mich nur nicht blamieren oder allzu herbe
> Kritik für für den Code einheimsen.
>
> Ich hoffe ihr seht mehr als ich.
> Bin mir nicht sicher ob ich F_CPU richtig definiert habe, aber das
> sollte für den Code erstmal uninteressant sein, da die ISR vom Timer
> davon ja erstmal nicht beeinflusst wird, oder?

Ich kann eigentlich nichts entdecken.

Daher ein paar Fragen:

Die ist klar, dass deine Overflow ISR in Realzeit nur alle 0.02 Sekunden 
ausgeführt wird? Das ist im Simulator eine lange Zeit. Da braucht der 
schon eine Weile, bis die Simulationszeit soweit fortgeschritten ist.

Setz zum Testen mal den Prescaler des Timers auf 1 anstelle von 1024. 
Siehst du den Timer im Simulator hochzählen? Wird die ISR jetzt 
angesprungen? Dann hast du einfach nur nich lange genug gewartet.

Woran machst du es fest, dass die Timer-ISR nie angesprungen wird? 
Stellst du das nur mit deinem Multimeter fest?
Programmier dir das mal um dass in der ISR eine LED eingeschaltet wird. 
Dann hast du eine eindeutige Kennung, dass sie ausgeführt wird.

von Florian T. (florian_t)


Lesenswert?

In der tat habe ich den Code falsch übernommen.

Das hier ist die original Vorlage die ich von Peter D. erhalten habe:
1
void sputchar( uint8_t c )
2
{
3
  c = ~c;
4
  STX_PORT &= ~(1<<STX_BIT);            // start bit
5
  for( uint8_t i = 10; i; i-- ){        // 10 bits
6
    _delay_us( 1e6 / BAUD );            // bit duration
7
    if( c & 1 )
8
      STX_PORT &= ~(1<<STX_BIT);        // data bit 0
9
    else
10
      STX_PORT |= 1<<STX_BIT;           // data bit 1 or stop bit
11
    c >>= 1;
12
  }
13
}

von Florian T. (florian_t)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Die ist klar, dass deine Overflow ISR in Realzeit nur alle 0.02 Sekunden
> ausgeführt wird? Das ist im Simulator eine lange Zeit. Da braucht der
> schon eine Weile, bis die Simulationszeit soweit fortgeschritten ist.
>
> Setz zum Testen mal den Prescaler des Timers auf 1 anstelle von 1024.
> Siehst du den Timer im Simulator hochzählen? Wird die ISR jetzt
> angesprungen? Dann hast du einfach nur nich lange genug gewartet.

Hah! In der Tat! Der Overflow wird ewig nicht aufgerufen.
Da habe ich wohl offensichtlich nicht darüber nachgedacht. :-)

Wie ist das mit der F_CPU? Habe ich die eigentlich richtig gesetzt, oder 
ist die falsch?

von Karl H. (kbuchegg)


Lesenswert?

Florian Trück schrieb:

> Wie ist das mit der F_CPU? Habe ich die eigentlich richtig gesetzt, oder
> ist die falsch?

Nö. Passt schon.
Der Optimizer muss eingeschaltet sein, damit das _delay_us korrekte 
Zeiten liefert. Und bei der Gelegenheit optimiert der Compiler die 
Floating Point Zahl sowieso weg.

WEnn dir unwohl dabei ist, dann schreibs halt als

#define F_CPU 9600000UL

dann kann dir nichts passieren.

von Florian T. (florian_t)


Lesenswert?

Da die Daten ja seriell übertragen werden sollen, stellt sich mir gerade 
die Frage ob ich noch einen Pegelwandler brauche, wenn ich den tiny an 
einen usb/seriell wandler hänge.
Oder kann ich den tiny direkt dran hängen und am PC daten empfangen?

von AVR-Newbie (Gast)


Lesenswert?

Florian Trück schrieb:
> Das Problem ist, dass der code in der IF-Bedingung nie ausgeführt wird.

Es scheint, dass der Interrupthändler (ISR) nicht angesprungen wird.
Ist d. Vektorname (TIM0_OVF_vect) korrekt?
Der Compiler ist an dieser Stelle sehr tolerant und bemeckert den Fehler 
nicht.
Als nächstes würde ich versuchen den zweiten Parameter mitzugeben.
Bei meinem Tiny26 muss ich den Händler so definieren:
1
ISR(TIMER0_OVF0_vect, ISR_BLOCK){
2
     tuMaWat();//…
3
   }
Sonst wird beim Überlauf wieder zu „main“ gesprungen…

Gruß
  AVR-Newbie

von Florian T. (florian_t)


Lesenswert?

AVR-Newbie schrieb im Beitrag #3004198:
> Bei meinem Tiny26 muss ich den Händler so definieren:ISR(TIMER0_OVF0_vect, 
ISR_BLOCK){
>      tuMaWat();//…
>    }
> Sonst wird beim Überlauf wieder zu „main“ gesprungen…

Danke für den Tipp, aber es scheint zumindest im Emulator nun zu 
funktionieren. Ich muss mich jetzt noch darum kümmern, dass der Tiny in 
Echt-Beschaltung auch funktioniert.

Karl Heinz Buchegger schrieb:
> Tipp für die Zukunft.
> An dieser Stelle ist eine simple LED das bessere Messinstrument. Denn
> eine LED siehst du auch dann noch flackern, wenn dein Voltmeter schon
> längst nur noch einen konstanten Wert anzeigt.

Das werde ich ausprobieren. Vielleicht sehe ich ja was flackern. :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.