Hallo zusammen, ich nutze beim ATmega88 den Timer1 als Waveform-Generator im CTC-Mode (Clear Timer on Compare) mit OCR1A als TOP-Wert und am Pin OC1B nehme ich das Signal ab. Funktioniert gut, das Rechteck auf dem Oszi entspricht der Erwartung. Das Problem: Bei Erreichen des Zählerwertes OCR1B, der kleiner als OCR1A ist, soll ein Interrupt ausgelöst werden. Der Interrupt kommt auch, aber erst bei OCR1A: d.h. wenn der Zähler löscht und von vorn anfängt. Warum wird OCR1B ignoriert? Ich dachte dass das zweite Output-Compare Register sich dafür eignet? Codeauszug: ; 16 Bit Timer/Counter 1 Initialisierung für das Signal ldi temp, 0b00010000 ; Toggle OC1B on compare match sts TCCR1A,temp ldi temp, 0b00001001 ; CTC mit OCR1A als TOP-Wert, ohne prescale sts TCCR1B,temp ldi temp, 0x7F ; Der Umschaltwert des 16 Bit Timers ldi temp2,0 sts OCR1AH, temp2 sts OCR1AL, temp ldi temp, 0x70 ; Interrupt kurz vor der Flanke zum Abtasten sts OCR1BH, temp2 sts OCR1BL, temp ldi temp, 0b00000100 ; Bit 2 OCIE1B: Timer/Counter1 Output Compare sts TIMSK1,temp ; Zur Kontrolle mit dem Oszi die LED kurz ein/aus OC1B_ISR: in save_sreg, SREG sbi PORTB,LED1 cbi PORTB,LED1 out SREG, save_sreg reti Die LED im Interrupt wird immer kurz nach dem Flankenwechsel geschaltet, leider unabhängig von OCR1B. Vielleicht bringe ich den Output-Compare Pin B mit dem Output-Compare B Register durcheinander, aber nach meiner Interpretation des Datenblatts werden Compare-Register und Pin separat gesteuert.
Holler schrieb: > Vielleicht bringe ich den Output-Compare Pin B mit dem Output-Compare B > Register durcheinander, aber nach meiner Interpretation des Datenblatts > werden Compare-Register und Pin separat gesteuert. Schon. Aber du schaltest (laut Kommentar) den OC1B Pin. Und der hängt vom nun mal nur vom OCR1B Compare Match ab. D.h. was du am Oszi maximal siehst, ist die Zeitverzögerung vom Auftreten des B-Compare Match (der den OC1B Pin toggelt) bis du dann in der ISR landest, in der du den LED Pin toggelst.
> ldi temp, 0b00000100 ; Bit 2 OCIE1B: Timer/Counter1 Output Compare
Mach doch nicht so einen Scheiss.
Wenn du OCIE1B setzen willst, dann schreib das als
ldi temp, 1<<OCIE1B ; OCIE1B: Timer/Counter1 Output Compare
ist eine Information weniger, die falsch sein kann. Bei dir muss ich
erst recht wieder kontrollieren, ob OCIE1B tatsächlich das Bit 2 ist. So
muss ich nur darauf aufpassen, ob OCIE1B tatsächlich im Register TIMSK1
ist.
> Warum wird OCR1B ignoriert? Die Pulse an der LED beweisen, dass er nicht ignoriert wird. Du hast irgendwo einen Denkfehler. Was siehst du am Oszi und was hättest du erwartet das du siehst? An deinem Code kann ich nicht erkennen, wie du diese Behauptung > Der Interrupt kommt auch, aber erst bei OCR1A: d.h. wenn der > Zähler löscht und von vorn anfängt. überprüfen könntest. Wenn der OCR1A auslöst, siehst du das nicht (es sei denn der Kommentar ldi temp, 0b00010000 ; Toggle OC1B on compare match ist falsch. Ich hab jetzt aber ehrlich gesagt keine Lust mir im Datenblatt rauszusuchen, wie das Bit an dieser Position heißt und ob das zu A oder B gehört. Schreib nächstes mal den Bitnamen hin, dann braucht man nicht im Datenblatt suchen.
Nein, das Toggeln des Pins ist im CTC-Mode ausschlieslich vom Wert im OCR1A abhängig. Da hat OCR1B keinen Einfluß. Welcher Pin dann toggelt steht im TCCR1A, Bit COM1A1, COM1B1, COM1A0, COM1B0. Ich habe nur COM1B0 gesetzt, das führt zum Toggeln des Pins OC1B.
Holler schrieb: > Nein, das Toggeln des Pins ist im CTC-Mode ausschlieslich vom Wert im > OCR1A abhängig. Da hat OCR1B keinen Einfluß. Sorry, aber das ist Unsinn. Der Pin OC1A reagiert bei Timer=OCR1A und der Pin OC1B reagiert bei Timer=OCR1B, egal welchen Modus du einstellst.
Sicher muss der Fehler irgendwo liegen. Aber der B-Pin toggelt ganz sicher in Abhängigkeit von OCR1A. Natürlich kann man das auch auf den A-Pin mappen, muss man aber nicht. Und der CTC-Mode geht meiner Meinung nach nur mit Steuerung über OCR1A, siehe angehängten Datenblattauszug. Wie schon gesagt, der OC1B toggelt perfekt. Mit OCR1A kann ich dessen Frequenz einstellen. Wo es klemmt, ist ein Interrupt zum Zeitpunkt bevor der Zähler OCR1A erreicht. Das wollte ich mit OCR1B auslösen, klappt aber nicht. Der ausgelöste Interrupt hat nichts mit dem Wert in dem Register zu tun. @ Karl Heinz Buchegger: sorry für die Bitmaps, werde zukünftig sowas wie ldi temp, 1<<OCIE1B schreiben.
Holler schrieb: > Sicher muss der Fehler irgendwo liegen. Aber der B-Pin toggelt ganz > sicher in Abhängigkeit von OCR1A. Lies es von unseren Lippen ab. Ganz sicher NICHT Es ist eigentlich ganz einfach: Alle Dinge mit einem B drinnen gehören zusammen und bilden eine Einheit. Alle Dinge mit einem A drinnen gehören zusammen und bilden eine Einheit. Es gibt da keine kanalübergreifende Funktionalität. > Und der CTC-Mode geht meiner Meinung nach nur mit Steuerung > über OCR1A, siehe angehängten Datenblattauszug. Das stimmt schon. Aber den OC1B Pin interessiert OCR1A nicht. (bzw. nur indirekt) > Mit OCR1A kann ich dessen Frequenz einstellen. Logisch kannst du das. Denn die Frequenz hängt aussschlisslich von OCR1A ab. Mit dem Compare Match in B kannst du eine Phasenverschiebung erreichen. Mehr aber auch nicht. Da du aber am OC1B nicht ablesen kannst, wann der Timer auf 0 zurückgesetzt wurde, hast du auch keinen Bezug für einen eventuellen Phasenversatz. Ergo bleibt nur die Frequenzänderung über OCR1A übrig.
Analogie: Uhr Deine Uhr tickt im Sekundentakt in OCR1A steht 59 drinnen. d.h. dein Timer (Uhr) zählt von 0 bis 59 (also 1 Minute lang. in OCR1B steht 15 drinnen. D.h. in jeder Minute, zur Sekunde 15, wird der Pin getoggelt. Schreibst du in OCR1B eine 28 rein, dann wird zur Sekunde 28 der Pin getoggelt. Aber: Von einem Toggeln zum nächsten vergeht nach wie vor 1 Minute. Denn dieser Zeitraum ist nicht von OCR1B abhängig. Der wird aussschliesslich von OCR1A (= den 59) gesteuert. Mit OCR1B kannst du den Zeitpunkt innerhalb dieser Minute festlegen, wann der Pin toggeln soll, aber nicht seine Frequenz. D.h. von aussen gesehen, wenn du nicht weißt, wann die Uhr ihr 60 erreicht hat und zurück gesetzt wird, siehst du an OC1B nur Pulse, die in 1 Minuten Intervallen kommen. Du hast keinen Bezug zu 0. Du müsstest dir den OC1A Pin freischalten um diesen 0-Bezug zu kriegen. Dann kannst du durch vergleich von OC1A und OC1B auch feststellen, zu welchem Zeitpunkt innerhalb der (durch OCR1A eingestellten) Minute der B-Interrupt kommt und der Pin getoggelt wird.
Es könnte ja so einfach sein: warum habe ich nicht einfach den Pin 13, also OC1A angelötet. Hab aber nun mal Pin 14 genommen, der heisst OC1B. Habe gerade nochmal kontrolliert. Hier ist (leider) kein Fehler. Anbei das Oszi-Bild: der Kanal 1 (gelb) hängt an OC1B, Kanal 2 (blau) an der LED der Interruptroutine: kann an OCR1B soviel drehen wie ich will, nichts verändert sich. Die Frequenz des Signal ist plausibel: Fsig = CPUclk / OCR1A = 128 kHz / 255 = 500 Hz. Der AVR läuft im extrem-Stromsparmode mit nur 128 kHz.
Holler schrieb: > Anbei das Oszi-Bild: der Kanal 1 (gelb) hängt an OC1B, Kanal 2 (blau) an > der LED der Interruptroutine: kann an OCR1B soviel drehen wie ich will, > nichts verändert sich. Wenn du eine Veränderung sehen willst, dann ändere den Interrupt von B nach A. Dann siehst du, wie sich durch Verändern von OCR1B die Signale zueinander verschieben.
@ Karl Heinz Buchegger Ich denke mal über die Analogie zur Uhr nach, aber heute schaffe ich das nicht mehr. Morgen Abend geht es weiter. Vielen Dank erst mal!
Holler schrieb: > Es könnte ja so einfach sein: warum habe ich nicht einfach den Pin 13, > also OC1A angelötet. Hab aber nun mal Pin 14 genommen, der heisst OC1B. > Habe gerade nochmal kontrolliert. Hier ist (leider) kein Fehler. Der Fehler ist in deinem Kopf. Mit diesem Setup ist auch nicht zu erwarten, dass sich irgendwas am Verhältnis der beiden Signale verändert. Deine Erwartungshaltung ist falsch. Das Oszi Bild spiegelt genau das wieder, was zu erwarten ist. Die blauen Pulse hängen zeitlich ein wenig hinter den gelben Flanken nach. Das ist der Zeitversatz, der vom Auftreten des Interrupts bis zum Anspringen der ISR und abarbeiten des Codes bis zum LED-Pintoggeln vergeht. Aber: Alle beiden Ereignisse sind an OCR1B gekoppelt (und indirekt an OCR1A, dieses Register steuert aber nur die Wiederholfrequnz. Mit einem zeitlichen Versatz der beiden Signale hat es nichts zu tun).
Stefan Ernst schrieb: > Wenn du eine Veränderung sehen willst, dann ändere den Interrupt von B > nach A. Dann siehst du, wie sich durch Verändern von OCR1B die Signale > zueinander verschieben. Habe jetzt sowohl Interrupt A als auch Interrupt B durch ein kurzes Pintoggeln markiert. Richtig: wenn ich OCR1B ändere, verschiebt sich der Zeitpunkt des Interrupts A. Mir ist klar, dass es sich um eine relative Verschiebung handelt. Ihr habt wohl Recht, dass OCR1A auf Pin A und OCR1B auf den Compare-Match des Pin B wirkt. So war es eine ungünstige Wahl den Pin B zu verwenden: geht zwar, ist aber irgendwie schwer nachzuvollziehen: - OCR1A muss wegen der Frequenz 0x7F sein. - wenn OCR1B = 0x7F oder 0 ist, löst der Interrupt A praktisch zeitgleich mit Interrupt B und dem Flankenwechsel an Pin B aus. - vergrößere ich OCR1B lansam von 0 beginnend, wandert der Interrupt A nach links. Ist nachvollziehbar, muss aber ziemlich um die Ecke denken. Anbei noch ein Oszi-Bild mit OCR1A=0x7F und OCR1B=0x10 CH1 (gelb) der Toggelnde Pin B CH2 (blau) der Interrupt B CH3 (lila) der Interrupt A Letzteren muss ich zum Abtasten nehmen, dann klappts! Vielen Dank, Problem erledigt!
Hi Mal ne dumme Frage: Warum muss es OCR1B sein. Der Interrupt von OCR1A würde in der gleichen Frequenz auslösen. Und einen Pin togglen kann OCR1A auch. MfG Spess
Für meine Schaltung brauche ich beide OCR1-Register: ich benötige einen Rechteck von bestimmter Frequenz (hier 500 Hz) und kurz vor der fallenden Flanke möchte ich ein externes Signal abtasten. Dazu eignet sich ein präzise ausgelöster Interrupt. - OCR1A definiert einen TOP-Wert, bei dem der Zähler löscht und von 0 wieder hochzählt. - OCR1B kann einen Interrupt B auslösen und zeitgleich Pin B (OC1B) toggeln. - OCR1A kann einen Interrupt A auslösen und zeitgleich Pin A (OC1A) toggeln. Da ich mein Rechecksignal an Pin B abnehme, muss ich Interrupt B verwenden um eine zeitliche Ablage zu erreichen. Hätte ich Pin A (OC1A) verwendet, hätte ich zum Abtasten den Interrupt B nehmen müssen und hätte mir das "um die Ecke denken" erspart. Wenn man sich das letzte Oszi-Bild ansieht passiert folgendes: - bei den lila Nadeln erreicht der Zähler 1 den Wert 0x7F des OCR1A, Interrupt A löst aus, der Zähler löscht => 0x0 - bei den blauen Nadeln hat der Zähler 0x10 erreicht, der Pin B toggelt, Interrupt B löst aus.
Holler schrieb: > Hätte ich Pin A (OC1A) verwendet, hätte ich zum Abtasten den Interrupt B > nehmen müssen und hätte mir das "um die Ecke denken" erspart. Noch ist Zeit. Messerchen, Fädeldraht, und die Hardware ist geändert. (Und gleich im Schaltplan für die Version 0.99 nachziehen) Es ist nicht ungewöhnlich, dass beim ersten Protoypen ein paar Fädeldrähte auftauchen. Der Schaltung tut das ja keinen Abbruch. Den Draht schön eng anlegen und so fixieren, dass man ihn nicht irrtümlich runterreißt.
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.