Hallo zusammen, ich habe einen Servocontroller 8-Servo Servokontroller aufgebaut und bin zur Zeit noch in der Entwicklungsphase. Ein großes Problem macht mir Timer0 mit dem A-Interrupt: Die Bedingung vom B-Interrupt gesetzt. Das komische dabei ist, dass wenn ich als Compare-Match-Wert für den B-Interrupt OCR0A=138 verwende geht es, drunter nicht mehr. Wie kann ich das ohne Workaround fixen? Was mache ich falsch? Die ganzen Sources findet ihr hier: http://umfragen-service.de/avr/ Grüße und Danke Michael
Nachtrag: Irgendwie scheinen sich die Compare-Matches zu bekriegen: Das Compare-Match, das größer ist, "gewinnt", bei dem anderen wird die Zeit nicht eingehalten... Hoffe, ihr könnt mir helfen...
Kannst du mal in Worten beschreiben, was die Timer-interrupts tun (sollen)?
Kurze Ablaufbeschreibung: Nach der Inizialiserung (servo_init()), soll das erste Interrupt (COMPARE MATCH A) denn PORTB auf high setzen und COMPARE MATCH B inizialiseren. COMPARE MATCH B soll genau nach 1ms aktiv sein. Die Interrupts werden nun deaktiviert. Jetzt soll der Treiber immer warten, bis er an ein gewisser Wert erreicht ist und dann die Servodaten ausgeben. Nun wird der Timer0 wieder gesetzt, dass er in 20ms mit COMPARE MATCH A weiter gemacht - so jedenfalls meine theoretischen Überlegungen. Aber irgendwie wird der entweder COMPARE MATCH A oder COMPARE MATCH B übersprungen. Wie kann ich das richten?
1 | ISR(TIMER0_COMPB_vect){ |
2 | ...
|
3 | do{ |
4 | // Warte ab, bis das es (das Flag) high ist
|
5 | loop_until_bit_is_set(TIFR,OCF0B); |
Das ist Schwachfug. Du kannst nicht in einem Interrupt warten, bis er wieder zuschlägt. Damit hast du genau 0 Zyklen für andere Interrupts und das Main übrig. Generell ist es dumm, in einem Interrupt überhaupt zu warten. Schmeiß mal das ganze Gedöns mit der Timermanipulation aus den Interrupts raus, da sieht doch keiner mehr durch und außerdem ist es Unsinn. Die Compareinterrupts sind doch genau dazu da, Dir den ganzen Timingablauf abzunehmen. Den T0 laß einfach durchlaufen und wenn etwas passieren soll, setzt Du den OCR0A auf T0 + Startzeit, und OCR0B auf T0 + Endezeit. Dann beide Pending flags löschen, beide Interrupts freigeben und fertsch. Und die beiden Interrupts machen dann nur das zu den beiden Zeiten gewünschte. Wenn sie single-shot sein sollen, löschen sie noch ihre eigene Interruptfreigabe. Aber mehr machen sie nicht mit den Timern rum. Peter
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.