Hallo Leute,
bin neu im Forum und ich finde es eine super Sache!
Ich arbeite mit einem ATtiny2313 und versuche das TOV0 ohne Interrupt
auszulesen. Der Timer0 arbeitet im normal Mode.
Hier mein Code:
if((TIFR&(1<<TOV0))==on)
{
TIFR=TIFR&0x01;
PORTB^=(1<<PB0);
}
Leider passiert nichts:-(
Wenn ich es aber mit der Interruptroutine versuche funktioniert es.
Kann mir jemand sagen wo der Fehler ist?
1 | |
Wie genau hast du "on" definiert? Das TOV0-Bit sitzt an 2. Stelle, d.h. wenn es gesetzt ist, ergibt die Abfrage für die if-Bedingung den Wert 2, wenn es nicht gesetzt ist, kommt 0 heraus.
1 | |
Um das Flag zu löschen, musst du eine 1 ins entsprechende Bit schreiben - und zwar mit der Anweisung TIFR=1<<TOV0.
Gast
#3151202
Hi,
das Problem dürfte wohl sein, dass du auf "== on" abfragst.
Je nachdem, wie du "on" definiert hast, wird das evtl. nie wahr sein.
(TIFR & (1<<TOV0)) ist nämlich 0, wenn TOV0 gelöscht ist, und 2, wenn
TOV0 gesetzt ist ( weil TOV0 Bit1 ist, also sieht das Ergebnis so aus
0b00000010 bzw 0x02)
Wenn du jetzt "on" als 1 definierst, kann das natürlich nie stimmen,
denn 1 != 2
Lass das "on" daher weg und frag einfach auf "ungleich 0" ab.
also:
if (TIFR&(1<<TOV0))
{
mach_was();
}
außerdem:
damit
TIFR=TIFR&0x01;
löschst du OCF0A: Output Compare Flag 0 A (weil das Bit0 ist) falls es
vorher gesetzt war.
Ich nehme an, du willst eigentlich TOV0 löschen
Das Overflow Flag löschst du so:
TIFR = (1<<TOV0);
Da es ein Interrupt Flag ist, muss es durch schreiben einer 1 gelöscht
werden (zumindest beim Atmega8 usw., nehme an, dass das beim Tiny2313
genauso ist)
Gast
#3151203
da war ich wohl zu langsam^^
Hi, Manchmal sieht man den Wald voller Bäume nicht;-) Genau das sind die Fehler. Ihr seid super, besten Dank!
Gast
#5962263
Hallo....ich hab das selbe Problem...nur dass ich das Flag genau so abfrage wie oben beschrieben ....if (TIFR&(1<<TOV0))...das funktioniert nicht...wenn ich dagegen genau so das ICF des Timer1 zum einfangen eines Signals am IC-Pin abfrage läuft alles super. Wenn ich mit der Interupt-Routine arbeite funktioniert es. Das heißt das Flag wird tatsächlich gesetzt, sonst würde ja auch kein Interupt ausgelöst. ich steh da schon ziemlich an...
Gast
#5962277
Harry schrieb: > Wenn ich mit der Interupt-Routine arbeite funktioniert es. Das heißt das > Flag wird tatsächlich gesetzt, sonst würde ja auch kein Interupt > ausgelöst. Du versuchst wahrscheinlich beides gleichzeitig zu tun. Das geht nicht, weil der ausgeführte Interrupt automatisch das Flag zurücksetzt. Dein Polling in main() sieht also niemals ein gesetztes Flag... Sprich: du musst dich entscheiden: Polling oder Interrupt. Oder du musst ein Hilfsflag im SRAM benutzen, welches du in der ISR setzt und in main() pollst.
Gast
#5962349
hatte ich ursprünglich auch geglaubt. Aber das ist nicht so. Schließlich hab ich eine eigenes kleines Testprogramm geschrieben, um der Sache auf den Grund zu gehen. Mit Interrupt klappt es. Ohne Interrupt gehts nicht. Dann dachte ich, dass eventuell der Timer0 einen Fehler hat. Also hab ich auf den Timer1 gewechselt - mit dem selben Ergebnis. Dann ganz genau kontrolliert ob der Timer im normalen Modus läuft - aber das Flag wird nicht erkannt. Bin ziemlich ratlos.
Gast
#5962352
Dann zeig doch mal den ganzen Code her.
Gast
#5962375
uint8_t testovf (void) / Testprogramm Timerüberläufen
{
uint16_t i;
i = 0; //allgemeine Zählervariable
TCCR0 |= (1<<CS00) ;
TCCR0 &= ~((1<<CS10) | (1<<CS20)); // Timer0 im CPU Takt gestartet
while(1)
{
while (!(TIFR & (TOV0))) // Schleife bis das overflowFlag erkannt
{
}
i++; // Zähler wird hochgezählt
TIFR |= (1<<TOV0); // Zurücksetzen des ÜberlaufFlags
if (i > 60000) // nach ca 0,7sek
{
if (PIND & (1<<PD3)) // Abrage von D3 (LED GRÜN)
{
PORTD &= ~(1<<PD3); // Toggeln des Ausganges LED
}
else
{
PORTD |= (1<<PD3);
}
i = 0; //Zurücksetzen des zählers
}
}
return(1);
}
Harry schrieb: > while (!(TIFR & (TOV0))) while (!(TIFR & (1 << TOV0))
Gast
#5962391
Du schreibst die Abfrage sehe wie iben aus, also so if (TIFR&(1<<TOV0)) Ich lese aber folgendes while (!(TIFR & (TOV0))) Musste meiner Meinung nach so aussehen while (!(TIFR & (1<<TOV0)))
Gast
#5962396
Ist eine Warteschleife die so lange durchlaufen wird, bis das Flag gesetzt wird. Statt dieser Schleife kann ich auch die if-Abfrage einfügen. Dann werden alle restlichen Abfragen halt auch ständig abgefragt. Egal...es funktioniert trotzdem nicht. Das gesetzte Flag wird nicht erkannt
Harry schrieb: > uint8_t testovf (void) / Testprogramm Timerüberläufen > { > uint16_t i; > i = 0; //allgemeine Zählervariable > > TCCR0 |= (1<<CS00) ; > TCCR0 &= ~((1<<CS10) | (1<<CS20)); // Timer0 im CPU Takt gestartet Was soll der Käse? Schreibb gescheite Werte DIREKT in das Register. SO!!!
1 | |
> while(1) > { > > while (!(TIFR & (TOV0))) // Schleife bis das overflowFlag erkannt FALSCH! Siehe Bitmanipulation! Eher so
1 | |
> { > } > i++; // Zähler wird hochgezählt > TIFR |= (1<<TOV0); // Zurücksetzen des ÜberlaufFlags Auch falsch! Die Flags werden durch ein Schreiben einer EINZIGEN '1' gelöscht, NICHT durch eine Oder-Verknüpfung mit dem aktuellen Inhalt.
1 | |
Denn mit der ODER-Verknüpfung kann man im Zweifelsfall andere, aktive IRQ-Flags löschen. Das mag HIER keine Rolle spielen, allgemein aber schon! Solche Fehler sind "nett", denn sie treten in komplexeren Programmen sehr sporadisch auf und man wird bei der Fehlersuche wahnsinnig! > > if (i > 60000) // nach ca 0,7sek > { > if (PIND & (1<<PD3)) // Abrage von D3 (LED GRÜN) > { > PORTD &= ~(1<<PD3); // Toggeln des Ausganges LED > } > else > { > PORTD |= (1<<PD3); > } > > i = 0; //Zurücksetzen des zählers > } Viel zu aufwändig. Das geht deutlich einfacher, XOR ist dein Freund, siehe Bitmanipulation.
1 | |
2 | |
3 | |
4 | |
5 | |
Gast
#5962398
ohh...alles zurück....grad erkannt. sorry
Gast
#5962402
...und wieder dazugelernt, dass ich in Zukunft keinen Code mehr poste
Harry schrieb: > ...und wieder dazugelernt, dass ich in Zukunft keinen Code mehr poste Deine Logik muss man nicht verstehen, oder? https://de.wikipedia.org/wiki/Generation_Snowflake
Gast
#5962412
Hättest du denn die Fehler ohne das Posten des Codes selber herausgefunden ?
Harry schrieb: > ohh...alles zurück....grad erkannt. sorry Harry schrieb: > ...und wieder dazugelernt, dass ich in Zukunft keinen Code mehr poste Erst nen uralten Thread kapern und dann nichts zur Lösung zu sagen. Bitte noch mehr unnütze Posts. Früher gab es mal die Sitte, die Lösung nochmal zusammen zu fassen und sich für die Hilfe zu bedanken.
Hi, glaube, in "asm" ist man bei sowas näher an der "Maschine" dran. Die Hochsprachen bringen - für mich jedenfalls - in dem Zusammenhang IMHO keine wesentlichen Vorteile. Jedenfalls habe ich 'mal ein Progrämmchen geschrieben, mit dem der Zustand der seriellen Schnittstelle überprüft werden sollte. Dabei werden dann Nullen bzw. Einsen auf dem 2 x 16 LCD angezeigt. Der Zustand der UART-Register. Also die wichtigsten Zeilen sind, evtl. erst Interrupts sperren mit "cli" Statusregister retten mit "in" Kopie des jeweiligen Registers auf "temp" mit "in" Dann Ausgaberoutinen mit Umrechnungsroutinen. etc. und Statusregister wiederherstellen mit "out" Interrupts wieder erlauben mit "sei" etc. etc. Prinzipiell könnte man auch die anderen Register auf die Art auslesen, also auch das TimerOverflow-Flag. Wichtig ist nur, dass man unter Umständen wie bei "atomic action" verfährt, um das eigentliche Programm nicht zu stören. Viel Spaß ciao gustav
c-hater schrieb: > Oder du musst > ein Hilfsflag im SRAM benutzen, welches du in der ISR setzt und in > main() pollst. Hallo, ich finde das auch als eine bessere Lösung. AVR haben GPIOR0-2, dabei sitzt GPIOR0 bei manchen AVR so, daß man den mit sbi-cbi erreichen kann. So kann ISR sehr kurz sein: Z.B. so:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Compiler macht daraus:
1 | |
2 | |
Danach kann man mit FL_ISR2 in Hauptprogramm alles Mögliche machen, ISR und Hauptprogramm stören einander nicht.
Hi, Ergänzung: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2543-AVR-ATtiny2313_Datasheet.pdf Seite 85. Auslesen funktioniert dann entsprechend. Seite 86. ciao gustav
Karl B. schrieb: >Seite_85.png >8,79 KB, 4 Downloads Selten so einen schlechten Screenshot gesehen! Wie schafft man das? Vorher ein Dutzend mal faxen?
Falk B. schrieb: > Selten so einen schlechten Screenshot gesehen! Wie schafft man das? > Vorher ein Dutzend mal faxen? Hi, sollte das Auffinden der entsprechenden Grafik auf dem Link erleichtern. Mehr nicht. Dazu reicht es allemal. ciao gustav
Karl B. schrieb: > Hi, > sollte das Auffinden der entsprechenden Grafik auf dem Link erleichtern. > Mehr nicht. > Dazu reicht es allemal. Dazu reicht ein Link auf Datenblatt bzw. eine Angabe der Seite! www.dummeausrede.de
Maxim B. schrieb: > Danach kann man mit FL_ISR2 in Hauptprogramm alles Mögliche machen, Kann man mit dem Interrrupt-Flag auch. > ISR und Hauptprogramm stören einander nicht. Keine ISR und Hauptprogramm auch nicht.
Thomas E. schrieb: > Kann man mit dem Interrrupt-Flag auch. Mit ISR-Flag muß man vorsichtiger umgehen, um andere Flags nicht zu berühren. Hier aber besteht solche Gefahr nicht. Man kann auch eine andere Variante benutzen: statt Flag einen Zähler. In ISR incrementiert, in Hauptprogramm auf 0 geprüft und wenn nicht, decrementiert und entsprechende Handlungen vorgenommen. Vorteil von dieser Variante: wenn diese Handlungen ab und zu, von laufenden Bedingungen abhängig, länger dauern als die Zeit zwischen ISR, gehen sie nicht verloren. Z.B. wenn gleichzeitig etwas kommt, was jede 1 ms gemacht wird und was jede 250 ms. Natürlich sollten die Handlungen im Durchschnitt statistisch kürzer sein als die Zeit zwischen ISR. Nachteil: kein ISR NAKED mehr möglich, da Register benutzt werden. Wenn Zähler mehr als 1 byte hat, sollte man ISR_BLOCK benutzen. Noch eine noch bessere Variante: Aufgabenreihe, evtl. zusammen mit Timerdienst. ISR stellt die Aufgabe auf die Reihe, dann wird die Aufgabe (irgendwann, wenn CPU die Zeit hat) gemacht.
Maxim B. schrieb: > Mit ISR-Flag muß man vorsichtiger umgehen, um andere Flags nicht zu > berühren. Hier aber besteht solche Gefahr nicht. Ja ne, is klar.
Falk B. schrieb: > Dazu reicht ein Link auf Datenblatt bzw. eine Angabe der Seite! Hi, steht doch da: Karl B. schrieb: > Hi, > Ergänzung: > > http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2543-AVR-ATtiny2313_Datasheet.pdf > > Seite 85. > Auslesen funktioniert dann entsprechend. > Seite 86. Doppelt gemoppelt hält besser. ;-) ciao gustav
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
