Hallo, ich sitze gerade vor nem seltsamen Problem mit einem Tiny24A. Den übrigen Code habe ich schon entfernt und mich an das Problem herangetastet. Vielleicht hat ja jemand von Euch eine Erklärung. Im Prinzip soll eine LED einfach nur blinken. Da zwischendurch noch was anderes gemacht wird, habe ich die Abfrage auf >500 gemacht, was aber die LED unregelmäßig blinken lässt. Schreibe ich == 500, funktioniert das Blinken bestens. Kann es sein, daß das Carry Bit in der Abfrage (einzigster Unterschied im Assembler) durch einen folgenden Interrupt irgendwie gelöscht wird? Hier noch der Codeausschnitt: #include <avr/io.h> #include <avr/interrupt.h> volatile unsigned int counter; int main(void) { DDRD |= (1<<PD5); PORTD &= ~(1<<PD5); TCCR0 = (1<<WGM01) | (1<<CS02); OCR0 = 239; TIMSK |= (1<<OCIE0); sei(); while(1) { if (counter > 500) { counter = 0x0000; PORTD ^= (1<<PD5); } } } ISR(TIMER0_COMP_vect) { counter = counter + 10; } Danke schon mal für alle Hinweise - irgendwie seh ich's einfach nicht...
Nachtrag: der gezeigte Code wurde auf einem ATMEGA32 ausgeführt (nur um Missverständnisse zu vermeiden). Wenn ich den Interrupt vor dem Vergleich sperre und danach wieder freigebe, dann funktioniert es auch bestens. Muß also damit was zu tun haben.
Counter ist 16 Bit breit, d.h. der Vergleich ist nicht atomar, muß also in zwei Schritten durchgeführt werden. Das gleiche gilt für die Zuweisung. Wenn genau zwischen den beiden Teilen der Operation der Interrupt ausgelöst wird, komt Mist raus. Die Lösung hast du ja schon selbst gefunden: AVRTester schrieb: > Wenn ich den Interrupt vor dem > Vergleich sperre und danach wieder freigebe, dann funktioniert es auch > bestens. Muß also damit was zu tun haben.
:
Bearbeitet durch User
Alles klar. Ich mache jetzt das Rücksetzen und Vergleichen in der ISR und setze dann nur noch eine 8Bit Variable mit nem Wert. So ein Kleinigkeit hat dann solche Auswirkungen, so daß man noch im Assembler schauen muß. Vielen Dank auf jeden Fall für den Hinweis!
AVRTester schrieb: > Alles klar. Ich mache jetzt das Rücksetzen und Vergleichen in der ISR > und setze dann nur noch eine 8Bit Variable mit nem Wert. Anstatt so kompliziert, kannst du auch gleich in der ISR den Portpin umschalten. Mann kann durchaus auch in einer ISR Dinge erledigen. Vor allen Dingen dann, wenn sie zeitlich einigermassen genau kommen sollen oder nicht unterbrochen werden dürfen. Man sollte es nur nicht übertreiben. Mit einem
1 | ISR(TIMER0_COMP_vect) |
2 | {
|
3 | counter = counter + 10; |
4 | |
5 | if( counter >= 500 ) { |
6 | counter = 0; |
7 | PORTD ^= (1<<PD5); |
8 | }
|
9 | }
|
begehst du höchstens den Fopas, dass kein Mensch weiss, was das umschalten am PD5 eigentlich bewirkt - da wäre eine bessere Bezeichnung angebracht. OK, man könnte noch kritisieren, dass man nicht um 10 erhöhen muss, sondern nur um 1, was die 16 Bit Arithmetik einsparen würde und 1 Byte weniger SRAM Verbauch bedeutet und man könnte die Variable in der ISR 'static' machen. Aber vom Prinzip her ist diese Lösung in dieser konkreten Situation besser, als erst mal umständlich ein Jobflag Variable zu bemühen, in der Hoffnung, dass in der Hauptschleife so zeitnah darauf reagiert werden kann, so dass keinem die manchmal zeitweilige Verkürzung des Intervalls auffällt. Diese LED hier blinkt solange die Interrupts aktiviert sind wirklich im angestrebten Takt. Egal was in der Hauptschleife passiert. 'ISR so kurz wie möglich' bedeutet NICHT, dass man gar nichts in einer ISR ereldigen darf. Es bedeutet nur, dass man dort keine Zeitfresser einbaut. Ob du einen Portpin umschaltest oder eine globale Variable auf 1 setzt, schenkt sich im Zeitverbrauch nichts.
:
Bearbeitet durch User
Danke für die Ideen, nur leider habe ich den Code total heruntergebrochen. In der Ursprungsschaltung ist leider die LED nicht direkt am ATTINY angeschlossen. Die LED hängt an einem FPGA, der mit dem Tiny über eine Art Pseudo SPI Interface kommuniziert (Tiny ist Master). Somit kann ich leider nicht alles in die ISR bringen, sondern muß die LED blinken lassen, wenn genug Zeit ist. Zusätzlich gibt es noch einen GPIO Interrupt, der in jedem Fall Vorrang hat. Ich habe nur für meine Problemfindung alles herausgenommen, damit mir die Hardware nicht dazwischenfunkt.
AVRTester schrieb: > Zusätzlich gibt es noch einen > GPIO Interrupt, der in jedem Fall Vorrang hat. Das ist allerdings ein Argument. Software SPI alleine wäre für mich noch kein Grund, den nicht direkt in einer ISR zu erledigen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.