Forum: Mikrocontroller und Digitale Elektronik Timer "verschluckt" sich


von Tom (Gast)


Lesenswert?

Guten Abend,

Mein Programm soll (u.A.) durch Drücken eines Tasters, welcher durch den 
Timer 0 ständig abgefragt wird, den Timer 1 aktivieren. In der Timer0 
ISR befinden sich alle Routinen zum Abfragen der Eingänge (Taster) und 
Timer 1 soll exakt jede Sekunde ein Interrupt liefern, sodass eine 
Variable runtergezählt werden kann. Die Variable wird dann in der Main 
als Bestandteil eines 7-Segment Zählers ausgewertet. Die Ausgabe erfolgt 
dabei über 3 7 Seg. Anzeigen.

Also, es wird eine Zeit eingestellt, die über die 3 7-Seg. Anzeigen 
angezeigt wird, bspw. 300 für 3 Minuten, 00 Sekunden. Wenn ich nun den 
Taster drücke, der ja alle paar ms durch Timer0 abgefragt wird, soll 
Timer 1 aktiviert werden, der dann in 1s-Schritten eine Variable 
runterzählt.

Soweit funktioniert alles, bis auf eine Kleinigkeit: Wenn ich den Taster 
drücke, passiert es manchmal, dass sich der Timer 1 beim ersten 
Runterzählschritt "verschluckt", er zählt also nicht ab der 1. Sekunde 1 
Sekunde herunter, also so: 3.59 - 3.58 - 3.57 usw, sondern überspringt 
die 3.59 manchmal ganz schnell, also eher in der Zeit eines Bruchteils 
einer Sekunde. Ab 3.38 läuft dann alles richtig.

Hier mal die Codeausschnitte:

void init()
{
TCCR0 = (1<<CS01);
TCNT0 = 0x00;      //Timer0 Startwert auf 0 setzen

TCCR1B = (1<<WGM12) | (1<<CS12); //Timer1 CTC, Vorteiler = 256
OCR1A = F_CPU / 256;     //Vergleichsregister laden mit Wert 31250
TCNT1 = 0;

TIMSK |= (1<<TOIE0);    //Timer 0 Overflow enable (Tasterabfragen)

sei();      //generelle Interruptfreigabe
}

ISR(TIMER0_OVF_vect)
{
   if(PORTB |= 1<< PORTB0)
   {
      TIMSK |= (1 << OCIE1A);
   }
}

ISR(TIMER1_COMPA_vect)
{

  d1--;    //-1 Sekunde
}


Das Ganze ist natürlich nur ein Ausschnitt. Ich versteh nicht, warum es 
manchmal nicht richtig geht. An der Entprellung der Taster kann es nicht 
liegen. Auch wird das Timer1-Zählregister Anfangs auf 0 gesetzt, so dass 
dort beim Starten des Timers keine wirren Werte stehen können. 
Beeinflusst Timer0 vielleicht Timer1?

Freue mich über jede Hilfe.

Grüße!

von Andreas W. (Gast)


Lesenswert?

Hi
1
ISR(TIMER1_COMPA_vect)
2
{
3
4
  d1--;    //-1 Sekunde
5
}

wo declarierst du d1? ich wird sagen das ist ein int oder? also 16Bit.

speere mal wenn du den wert setzt die interrupts. Dann geht es ohne 
"verschlucken" oder du machst es zu einen uint8_t.

Siehe Stichwort atomarer Zugriff.

von Tom (Gast)


Lesenswert?

d1 wird global als volatile uint8_t deklariert. Kann also nicht daran 
liegen. Irgendwie scheint der permanent das Register TCNT1 zu zählen, 
anders kann ichs mir nicht erklären. Wenn ich nämlich gleich vor "TIMSK 
|= (1 << OCIE1A); " in der Timer0 ISR TCNT1 lösche (also mit TCNT1 = 0), 
funktionert es. Aber das kann ja auch nicht die Lösung sein, denn sonnst 
wird Timer1 immer wieder "resettet", wenn ich den Taster auch während 
des Zählens drücke. Oder wird generell nach der Timer1 Initialisierung 
(wie in init) das Register TCNT1 gezählt, obwohl Timer1 noch gar nicht 
durch "TIMSK |= (1 << OCIE1A);" freigegeben wurde?

von Johannes M. (johnny-m)


Lesenswert?

> if(PORTB |= 1<< PORTB0)
Meinste nicht, da wäre PINB sinnvoller? Und ein "&" anstelle des "|="? 
Oder übersehe ich da was funktionelles? Der Ausdruck dürfte so, wie er 
da steht, immer wahr sein.

von Andreas W. (Gast)


Lesenswert?

der Timer zählt nach der Iinitialisierung, das ist unabhängig vom 
auslösen des Interrupts.

von Thomas (Gast)


Lesenswert?

Nee, ist klar. Hab das auch im Programm so. Ich hab das fürs Forum nur 
fix umgeschrieben, weil alles über #defines läuft und da ich die der 
übersichtlichkeitshalber nicht auch noch einfügen wollte, hab ichs eben 
so gemacht. Danke für den Hinweis. Also, muss heißen:

if(PINB |= 1<< PINB0)
   {
      TIMSK |= (1 << OCIE1A);
   }

von Thomas (Gast)


Lesenswert?

Ja und natürlich ein & statt |, sorry.

von Johannes M. (johnny-m)


Lesenswert?

Thomas wrote:
> Also, muss heißen:
>
> if(PINB |= 1<< PINB0)
Das ist immer noch falsch! Es macht so keinen Sinn, abgesehen davon, 
dass der Ausdruck in den Klammern immer wahr ist!

von Johannes M. (johnny-m)


Lesenswert?

Thomas wrote:
> Ja und natürlich ein & statt |, sorry.
...Und kein "="!

von Thomas (Gast)


Lesenswert?

Hab das Problem gelöst. Vielen Dank nochmals.

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.