Hallo liebe Community, ich versuche mit einem atmega162 die Tastendrücke, die ein VW-Radio an CD-Wechsler meldet, auszuwerten. Laut Protocol-Beschreibung (und das sehe ich auch mit dem LA) kommt erst 9 ms-langer high-Impuls, dass 4,5 ms low, und dann kommen 32 bits von Command, die als (0,550 ms high + 0,550ms low) für 0 und (0,550 ms high + 1,7 ms low) für 1 kodiert sind. Stimmt alles, abgeguckt mit LA direkt am Pin 12 des atmega's; Pegeln vom Radio sind 0V-5V, Ausgang des Radios ist über zwei 74HC14-Elemente an INT0 angeschlossen. Als erstes wollte ich einfach die Längen der Impulse zwischen steigender und fallender Flanken messen, mit denen ein Array von 32 Stellen füllen und das Ergebnis mit UART auszugeben nur irgendwie klappt es bei mir nicht. Device reagiert auf die Sendung vom Radio und gibt das Array über UART aus, nur die gemessenen Längen stimmen überhaupt nicht: alle Werte im Array sind dann entwender 00 oder 01 :( Was mache ich event. falsch in dem untenstehenden Code? (kompiliert mit der letzten WinAVR-Version) : void main(void) { SBI(MCUCR, ISC01);SBI(MCUCR, ISC00); //rising edge by start while (1) { } } void start_T2() { TCNT2 = 0x00; //clock period = 128 us SBI(TCCR2, CS22);SBI(TCCR2, CS21);SBI(TCCR2, CS20); } void stop_T2() { CBI(TCCR2, CS22);CBI(TCCR2, CS21);CBI(TCCR2, CS20);//clear bits } volatile int count = 0; volatile int state = 0; volatile uint8 lengthes[32]; SIGNAL(SIG_INTERRUPT0) { if (state==0) { //set from rising to falling edge SBI(MCUCR, ISC01);CBI(MCUCR, ISC00); start_T2(); state = 1; } if (state==1) { //set back to rising edge SBI(MCUCR, ISC01);SBI(MCUCR, ISC00); lengthes[count] = TCNT2; stop_T2(); state = 0; ++count; if (count>31) { for (int i=0;i<32;++i) { UART_Printfu08(lengthes[i]); EOL(); } count = 0; } } }
SIGNAL, SBI, CBI... sind längst veraltet (und was CBI und SBI angeht, die werden afaik gar nicht mehr unterstützt). Du müsstest eigentlich beim Compilieren eine ganze Latte Warnungen und Fehlermeldungen bekommen... Außerdem: Der obige Code ist mit Sicherheit unvollständig. Warum schickst Du kein vollständiges Programm? Und noch was: Impulslängenmessung macht man mit Input Capture und nicht über externe Interrupts. Und: Serielle Ausgaben haben in Interrupt-Handlern nichts verloren. Da brauchste Dich nicht zu wundern, wenn es Timing-Probleme gibt.
Der Compiler bringt keine Warnungen aus, ausser cdc.c:30: warning: function declaration isn't a prototype cdc.c:34: warning: function declaration isn't a prototype SBI/CBI/SIGNAL benutze ich an anderen Stellen des Projektes und die funktionieren einwandfrei; wegen serieller Ausgabe hast du formal Recht, das ist aber nur ein Versuch, die Längen zu messen; die Ausgabe erfolgt erst nachdem die ersten 32 Impulse gemessen sind und damit dürfte keinerlei Timing-Probleme zumindest für die ersten 32 Messungen herrvorrufen; ich habe schon versucht das Array beim Empfangen eines bestimmten Charakters mit SIGNAL(SIG_USART0_RECV) in uart.c auszugeben - mit gleichem Endergebnis; der Unterschied zu ICP liegt m.E. nur daran, dass ich da Noise unterdrucken kann :/ - nur ich habe hier keinen Noise, sonst würde INTO auch beim Noise ausgelöst. Den Quellcode komplett poste ich gleich.
Tja, mit den Warnungen kann man herzlich wenig anfangen, wenn man nicht weiß, auf was sich die Zeilennummern beziehen...
habe gestern dem Rat von johny.m gefolgt und ICP benutzt - mit dem geht es auf einmal :) Code: int count = 0; u08 lengthes[32]; u16 lengthes_16[72]; void cdc_init(void) { SBI(TCCR1B, ICNC1); CBI(TCCR1B, ICES1); //falling SBI(TIMSK , TICIE1); SBI(TCCR1B, CS12);CBI(TCCR1B, CS11);CBI(TCCR1B, CS10); } SIGNAL(SIG_INPUT_CAPTURE1) { uint16 length = ICR1; lengthes_16[count] = length; TCNT1 = 0x0000; ++count; if (count>71) count = 0; } void printL() { for (int i=0;i<72;++i) { UART_Printfu16(lengthes_16[i]); EOL(); lengthes_16[i] = 0x0000; } }
Wenn du jetzt noch SIGNAL durch ISR ersetzt und TIMER1_CAPT_vect für den Namen des Vektors, bist du auf dem aktuellen Stand. Außerdem ist deine Benutzung der CBI- und SBI-Makros der beste Beweis, warum man solche Makros wirklich nicht haben will. All deine umständlichen und codeintensiven Aktionen (die noch dazu kurzzeitig den Timer mit einem nicht gewollten Prescaler betreiben) lassen sich einfach durch:
1 | TCCR1B = _BV(ICNC1) | _BV(CS12); |
ersetzen.
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.