Forum: Mikrocontroller und Digitale Elektronik Timer0 Abfrage


von semo (Gast)


Lesenswert?

Hi Leute!

Folgender Text hat mich grad etwas "verwirrt" (ist aba wahrscheinlich
nur ein Denkfehler):
  "The bit TOV0 is set (one) when an overflow occurs in
  Timer/Counter0. TOV0 is cleared by hardware when executing the
  corresponding interrupt Handling Vector. Alternatively,
  TOV0 is cleared by writing a logic one to the flag. When the SREG I-
bit, TOIE0 (Timer/Counter0 Overflow Interrupt Enable), and TOV0 are
  set (one), the Timer/Counter0 Overflow interrupt is executed."

-> Das Overflow-Flag vom Timer 0 wird ja auf "1" gesetzt wenn ein
   Overflow kommt, ok alles klar - aber wie kann ich es dann löschen
   indem ich es auf 1 setzen muss? Gibts da in der schreibweise
   ("set" bzw. "logical one") einen unterschied?

-> wie schaut der Befehl genau aus, um abzufragen ob TOV0 gesetzt ist
und wenn ja, wie wird es dann wieda gelöscht?

besten Dank im vorraus!
gruß,
semo

von semo (Gast)


Lesenswert?

achja, verwende ATMEGA8!
;o)

semo

von Rahul (Gast)


Lesenswert?

hmmm... mal sehen:

Das TOV0-Bit wird gesetzt, sobald ein Überlauf auftritt. Hast Du!
Zum Löschen wird entweder die Interrupt-Routine aufgerufen und das Bit
hardwaremässig gelöscht. Hast Du!
Will man es manuell löschen, muss man das Bit setzen. Ist zwar etwas
komisch, aber es gibt noch weitere Bits, die auf diesem Weg gelöscht
werden.
Abfragen kannst du es mit den üblichen Abfrageoperationen in C z.B.
mit ("Timerregister" && (1<<TOV0)); (Ich weiß gerade nicht, wie das
Register-Byte heisst...).
Vielleicht hilft dir das ja...
Gruß Rahul

von Axel Rühl (Gast)


Lesenswert?

Hi,
steht doch da aber so richtig da...
das Flag wird gesetzt, wenn der Timeroverflow auftrat. Dieses bleibt
solange gesetzt, bis der Atmel endlich Zeit gefunden hat, in die
Interruptroutine zu springen (kann ja sein, das Du das gerade mit
"cli" verboten hattest). Jetzt springt der AVR in seine Timer0
Routine und das Flag wird gelöscht damit in der Zwischenzeit ein
eventuel erneut auftretender Interrupt nicht verloren geht. Das gleiche
gilt ja auch für die ganzen anderen Interrupts. immer wenn einer
auftritt, merkt sich das der AVR und wenn Zeit ist(also das "i"Flag
gestzt), werden diese in Rangfolge ihrer Priorität abgearbeitet. Ob das
Bit nun High-oder Low-Pegel hat, wenn es gesetzt oder gelöscht ist steht
doch nirgends...

Wie man dis jetzt abfragt? habe ich noch nicht gemacht, glaube ich.

Wann muss man denn das abfrgaen?

AxelR.

von Peter D. (peda)


Lesenswert?

Schön, daß Du Dir das Datenblatt zuerst durchliest und nicht tagelang
verzweifelt den Fehler suchst.

Ja es ist so, manche Bits müssen auf 1 gesetzt werden und sind dann
hinterher 0.
Der Befehl ist der gleiche, wie wenn Du einen Portpin auf 1 setzen
willst (der ist dann aber auch 1).


Irgendwie wollen manche Entwickler eine eigene Note reinbringen
(Duftmarke setzen), auch wenn sie damit Scharen von Programmierern in
die Verzweiflung treiben.

Und die AVR-Entwickler haben sich nun mal diesen Blödsinn ausgedacht
und Dir bleibt leider nichts weiter übrig, als Dich damit abzufinden
und es auch ständig im Hinterkopf zu behalten.


Peter

von semo (Gast)


Lesenswert?

Hi Rahul!

danke, bin also doch net so falsch gelegen wie ich dachte...
zum Abfragen:  if (TIFR & (1<<TOV0)) {    //Kontrolliere, ob TOV0-Bit
                                          //in TIFR gesetzt ist

zum Löschen:    TIFR &=  ~(1<<TOV0);

müsste also stimmen, oder?

gruß,
semo

von Peter D. (peda)


Lesenswert?

Nein !

zum Löschen:    TIFR |=  (1<<TOV0);


Peter

von Peter D. (peda)


Lesenswert?

Implizit bedeutet das auch, Du kannst ein solches Bit nie selber setzen,
um z.B. einen Softwareinterrupt zu erzeugen.


Peter

von semo (Gast)


Lesenswert?

danke peter

von Peter D. (peda)


Lesenswert?

Da ist deshalb noch ne böse Falle drin !

Da das TOV1 ebenso blöde ist und mit im selben Register sitzt, wird es
automatisch mit gelöscht.

Deshalb geht das hier auch:

zum Löschen:    TIFR &=  ~(1<<TOV1);

Das löscht alle blöden Bits im TIFR mit Ausnahme des TOV1.

Ich hoffe, ich habe Dich jetzt nicht zu sehr verwirrt.


Peter

von semo (Gast)


Lesenswert?

also, ich glaub bei mir stimmt irgendwas mit dem timer oder so nicht...

habe folgende funktion für eine warte-zeit:


void delay_ms (unsigned int x) {
  int c=0;

  while (c < x) {
    TCNT0=0x62;  //  Timer0 value for  10ms steps (0x62 = 98
          TIFR |=  (1<<TOV0);
    if (TIFR & (1<<TOV0)) {
    c++;
                USART_transmit_string("c++");
          }
  }
}

-> somit würde ich doch z.B. bei "delay_ms(5)" eine verzögerung von
50ms erreichen, oder!? Aber es schaut so aus als würde ich garnet in
die if-Schleife kommen (hab mir zur kontrolle was am PC anzeigen
lassen)! Der Code müsste doch stimmen, oder?

siehst du vielleicht einen fehler?

gruß,
semo

von semo (Gast)


Lesenswert?

ok, alles klar...glaube hab den fehler gefunden (bin anscheinend
zwischen while + if "steckengeblieben"!)

void delay_ms (unsigned int x) {
  int c=0;
  TCNT0=0x62;
  TIFR |=  (1<<TOV0);

  while (c < x) {
    if (TIFR & (1<<TOV0)) {
      c++;
      TIFR |=  (1<<TOV0);
      TCNT0=0x62;
    }
  }
}

so müsste es jetzt klappen!
,o)

semo

von Thomas (Gast)


Lesenswert?

Hallo,
ich weiß, der Beitrag ist alt. Ich bin drauf gestoßen bei der Suche nach 
einer Lösung.
Würde gerne im Atmega32 den Timer0 Interrupt an einer bestimmten Stelle 
auslösen. Er könnte zufällig schon gerade feuern, falls aber nicht so 
will ich das dort erzwingen um den Timer an einer bestimmten Stelle 
"frisch" loszählen zu lassen.
Wie mache ich das? Peter schreibt ja dass es so nicht geht, wie denn 
dann?

Schönen Sonntag und danke für ein Feedback

Thomas

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.