www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer springt - Sekundentakt hüpft


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Jens (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Meine "void Wait(uint16_t a)" Funktion sieht so aus:

- eine Variable (a) wird in der Interruptroutine runtergezählt bis sie 
gleich Null ist. Timer0 OVF  if(a!=0) a--;

- Die Waitfunktion wartet einfach nur bis a = 0 ist. while(a != 0)
dann ist die Pause zu Ende.

Sobald aber "a" größer als 255, also 16Bit groß ist, kommt es zu 
Aussetzern.

Lasse ich z.B. eine Led blinken, dann geht es 5 bis 10 mal gut, dann 
gibt es einen Sprung, nur kurzes Aufleuchten. WDR ist abgeschaltet, auch 
alle anderen IR habe ich mal weggenommen. Bei 8Bit (<256) geht es 
perfekt.

Könnt Ihr helfen?

Autor: Ingo L. (gleichisesschrott)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Programm zeigen

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Du musst den Zugriff auf a in der Waitfunktion atomar machen.

Autor: Ralph (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Na ist relativ einfach zu erklären.

Du hast eine 16 Bit Variable auf einem 8 Bit µC

Fall 1: Der Wert ist zwischen 0 und 255.
Es wird nur ein Byte der Variable genutzt
==> R/W Zugriff auf das höhere Byte ist egal, da eine 0 mit einer 0 
beschrieben / gelesen wird.
==> R/W zugriff auf das niedrige Byte ist eine einzelner Zugriff der 
nicht unterbrochen werden kann.
==> alles gut :-)

Fall 2: Der Wert ist > 255
==> R/W Zugriff auf das höhere Byte erfolgt.
==> und jetzt kommt der böse Interrupt und verändert den Zähler
==> R/W Zugriff auf das niedrige Byte erfolgt dann NACH dem Interrupt.

==> Variablen Wert ist somit korrumpiert worden. ==> Müll

Und das ist dein Problem.


Stichworte zur Lösung:
* Interrupt sperre während der Variablenbearbeitung
* Volatile
* 2 Variablen nutzen mit definierter Werteübergabe

Autor: Jens (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
wie atomar?

Das Programm ist ganz simpel.

int main(void)
{
 TCCR0 =  3;  
 TIMSK |= (1<<TOIE0);

 InitPorts();

 sei();

 while(1)
 {
   LedOn;    //Macro
   Wait(500);     // bei 255 geht es bestens
   LedOff;   //Macro
   Wait(500);
 }
}

...

ISR(TIMER0_OVF_vect)
{
  if (TimerWait != 0) TimerWait --;
}
...

void Wait(uint16_t b)
{
  TimerWait = b;

  while(TimerWait != 0)
  {
    b += 1;  // nur so, damit ich beim Simulieren
    b -= 1;  // b verändern kann
  }
}

...

volatile uint16_t     TimerWait;

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Jens schrieb:
> wie atomar?
>
> Das Programm ist ganz simpel.

Eben ein wenig zuu simpel.
Der Vergleich in dieser Schleife "while(TimerWait != 0)" erfolgt in 
mehreren Schritten. Wenn der Interrupt zwischen drin kommt, kann es 
Probleme geben:
- TimerWait ist 0x0100
- der Vergleich beginnt mit dem Low-Byte, das ist gleich 0
- jetzt kommt der Interrupt und ändert TimerWait auf 0x00ff
- der Vergleich macht weiter mit dem High-Byte, das ist auch gleich 0
=> Bedingung ist false, Schleife bricht ab

Autor: Jens (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
ja, habe ich verstanden, Danke, kann mich auch an die Zeiten das 
Assembler-Programmierens erinnern - sehr lange her.

Wie kann man es einfach ändern? Ich dachte volatile für TimerWait 
reicht.

Autor: Falk Brunner (falk)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Siehe Interrupt.

Autor: Jens (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Danke, dann werde ich das so machen, dass nur ein Flag in der IR-Routine 
gesetzt wird und der Timer im Hauptprogramm, wenn Flag=1, ggf. -- 
gesetzt wird.

Bedeutet "atomar" also lediglich, darauf achten, dass es nicht zur 
"Zerspaltung" der 16Bit Varianlen kommt?

Autor: Ralph (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Jens schrieb:
> Bedeutet "atomar" also lediglich, darauf achten, dass es nicht zur
> "Zerspaltung" der 16Bit Varianlen kommt?
>

ja, gilt aber auch genauso für 32 , 64 , .... Bit Variablen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net