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?
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
TIFR=TIFR&0x01;
Um das Flag zu löschen, musst du eine 1 ins entsprechende Bit schreiben
- und zwar mit der Anweisung TIFR=1<<TOV0.
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)
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...
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.
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.
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)))
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
TCCR0=(1<<CS00);// Prescaler 1 und los
> while(1)> {>> while (!(TIFR & (TOV0))) // Schleife bis das overflowFlag erkannt
FALSCH! Siehe Bitmanipulation! Eher so
1
while(!(TIFR&(1<<TOV0)))
> {> }> 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
TIFR=(1<<TOV0);
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.
Harry schrieb:> ohh...alles zurück....grad erkannt. sorryHarry 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
#define FLAGG GPIOR0
2
#define FL_ISR2 7 // ISR 2
3
4
ISR(INT2_vect,ISR_NAKED){
5
FLAGG|=(1<<FL_ISR2);
6
reti();
7
}
Compiler macht daraus:
1
sbi 0x1e, 7
2
reti
Danach kann man mit FL_ISR2 in Hauptprogramm alles Mögliche machen, ISR
und Hauptprogramm stören einander nicht.
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.