Hallo,
um den RC5 Code meiner Fernbedienung zu decoden, will ich nach
einstellbarer Zeit(889µs wie bei RC5 üblich) ein Interupt. Das ganze
soll auf dem Timer1 des ATmega88P ablaufen. Bisher habe ich versucht das
Compareregister immer um 889µs weiter als den Timerstand zu stellen.
1
lds tmp, TCNT1L
2
lds tmp2, TCNT1H
3
ldi tmp3, 111 ;in 889µs soll er auslösen!
4
;Prescaler=64 bei 8MHz(->8µs)
5
add tmp, tmp3
6
clr tmp3
7
adc tmp2, tmp3
8
sts OCR1AL, tmp
9
sts OCR1AH, tmp2
Mein Programm ablauf ist folgender:
1.Pinchangeinterupt->Pinchangeinterupts werden deaktiviert(PCMSK0);
Timerinterupts aktiviert UND Compareregister wird um 444µs weiter als
TCNT1 gestellt
2.Nach 444µs wird ein Timerinterupt ausgelöst; ab diesem Zeitpunkt läuft
der Timer auf 889µs
3.Letztes Timerinterupt für diese RC5-Sequnz, weil danach vorerst
Sendepause ist->Timerinterupt abgeschaltet; Pinchange an
Jetzt ist das Problem, dass bei einem erneuten Pinchangeinterupt der
Timerinterupt nicht nach 444µs sondern 889µs auslöst!?
Beim ersten Pinchange funktioniert es richtig, beim zweiten löst er nach
889µs aus.
Im Anhang finden sich der ASM-Code und zwei Screenschots vom Timing(mit
Soundkarte aufgezeichent!!)
Tus nicht. Der AVR hat deswegen eine eigene reti Instruktion, damit du
eben keinen sei brauchst. Und das ist auch gut so. Denn nur so ist
gewährleistet, dass eine ISR auch tatsächlich komplett abgeschlossen
ist, ehe der nächste Interrupt für den Aufruf der nächsten ISR sorgen
kann.
Schwerwiegender allerdings (wenn ich mich nicht verschaut habe) ist es,
dass die Anzahl der push/pop in der zweiten ISR nicht stimmt. Du popst
einmal zu viel.
1
rc5_ir_over1:
2
3
push tmp2 ; 1
4
push tmp3 ; 2
5
push tmp ; 3
6
7
....
8
9
10
pop tmp ; 2
11
12
....
13
14
pop tmp3 ; 1
15
pop tmp2 ; 0
16
pop tmp ; ooops. Das war die Return Adresse
17
sei
18
reti
Und das SREG solltest du während einer ISR auch sichern.
Karl Heinz Buchegger schrieb:> Schwerwiegender allerdings (wenn ich mich nicht verschaut habe) ist es,> dass die Anzahl der push/pop in der zweiten ISR nicht stimmt. Du popst> einmal zu viel.
Du hast dich leider verschaut bzw. ich zu wenig kommentiert.
Auf "rc5_ir_over1" wird nicht von außen gesprungen, sondern nur inerhalb
der ISR namens: "rc5_ir_CM1A:"
> Und das SREG solltest du während einer ISR auch sichern.
Ja, das sollte ich wirklich tun..., Danke für den Hinweis!
Übrigens,
diese Zeilen stehen noch im Hautpprogramm
(Das ich aus Platzgründen weggelassen habe, sowie die restlichen 7
files):
Der Timer läuft nach dem Compare weiter. Wenn Du also den neuen
Comparewert zum Timer addierst, dauert es länger bis zum nächsten
Interrupt.
Besser daher die Zeit zum alten Comparewert addieren, dann stimmt die
Zeit zwischen 2 Interrupts genau.
Peter
Peter Dannegger schrieb:
> To do a 16-bit write, the high byte must be written before the low byte.
Ich hab die Zeile drüber gelesen, wo in meinem Datasheet stand:
"Not all 16-bit accesses uses the temporary register for the high byte.
Reading the OCR1A/B 16- bit registers does not involve using the
temporary register."
Durch verlesen glaubte ich des gilt auch für schreiben
Peter Dannegger schrieb:
>Der Timer läuft nach dem Compare weiter. Wenn Du also den neuen>Comparewert zum Timer addierst, dauert es länger bis zum nächsten>Interrupt.>Besser daher die Zeit zum alten Comparewert addieren, dann stimmt die>Zeit zwischen 2 Interrupts genau.
Kling gut, werd ich umsetzen. Aber ist das bei einem Prescaler von 64
nicht egal?
Ich schreibs um und meld mich dann nochmal, Danke für eure Hilfe!
julian
Hier nochmal der überarbeitete Code(s. Anhang)
>Wie wäre es mal mit einem assemblierbaren Code.
Ich hab eine Datei, die ich auf die schnelle gebaut hab angehängt.
Jedoch ist das Problem, dass ich das ganze auf meiner WordClock
Variante1 zugeschnitten programmiere.
Zum Timing:
irgendwie bricht der µC die Analyse nach dem 6.Mal ab, bis auf den
PinChange-interupt rührt sich nichts mehr!
Auserdem besteht weiterhin das Problem, das sich die allererste Sequenz
von den folgenden im 1Timer-Interupt unterscheidet. In der 1.Sequenz
läuft nalles so wie geplant, und ab dann wird der 1.Timerinterupt, der
auf den Pinchange folgt, ignoriert, jedoch werden die 680µs zu den 889µs
dazugezählt.
Eigentlich könnte ich diesen Effekt nutzen und die 1.Sequenz als
"falsch" ansehehn.
julian
Guten morgen,
hab mich heute gleich hingesetzt und noch etwas die FB gedrückt und
meinen Code etwas umgeschrieben.
Ich hab geschrieben:
>Zum Timing:>irgendwie bricht der µC die Analyse nach dem 6.Mal ab, bis auf den>PinChange-interupt rührt sich nichts mehr!
Hab dieses Problem gelöst, der Fehler lag daran, dass ein Codeteil den
Timercounter zurüpckgesetzt hat. Hab diesen Codeteil entfert und jetzt
ist das Problem Geschichte!!
Bei erneute Aufzeichnungen ist mir das im Anhang gezeigte Bild ins Auge
gefallen:
blau:680µs
grün:889µs
braun:680µs+889µs ungefähr 1,6µs
rot-vertikal:Fehler ist aufgetreten!
Erstaunlicherweise kommt mitten!! in der Sequenz dieses Bild zum
Vorschein.
Darauf sieht man dass nach vielen Anaysen, jetzt bei einer Schlechten
Übertragung auf einmal die gewünschten 680µs zwischen dem Pinchange und
dem Timerinterupt sind. Ich hab leider keine Erklärung für dieses
Phänomen.
Kompletter Code(inklusive Projektdateien des AVR-Studios) gezippt
ebendfalls Angehängt!
julian
Eigentlich wollte ich den CTC-mode nicht verwenden, weil ich dann das
zweite Comparegister vergessen kann. Da das ganze jedoch nicht so funzt
wie es soll, find ich es eigentlich gar keine schlechte Idee mehr, CTC
zu verwenden.
Was würdet ihr an folgendem Programmablauf verbessern:
Die Struktur meines Programms kann ich ja im groben beibehalten(?)
1.bei einem Pinchange-INT muss ich meine 680µs einstellen, und TCNT1 auf
null setzen.
2.Beim ersten CTC-INT muss ich die Comparezeit hochstellen, TCNT1 kan
ich
lassen, das es sowieso null ist!?
3.Jetzt meine 27 CTC-INT abwarten und dann
4.PinChange-INT wieder freigeben
julian
Um euch auf dem laufendem zu halten:
CTC-mode vergess ich wieder, ich hab jetzt rausgefunden, warums nach dem
PinChange Interupt 680µs+ 889µs waren, und das nie beim ersten
PinCHange-INT:
Wurde einmal der TimerINT aufgerufen, und danach beendet, so ist nach
889µs die OC1A-Flag gesetzt gewesen. Ist jetz wieder die PinChangeISR
aufgerufen worden, wurde der TimerINT enabled und direkt nach der PC-ISR
ist ein OC-ISR gestartet, die nochmal 889µs zum OCR1A dazugezählt hat.
Somit waren zwischen zwei OC-ISR's 680µs(von PC-ISR eingestellt) plus
die 889µs(von OutputCompare-ISR eingestellt) 1,5ms zwischen Zwei
Timerinterupts, die ich auf meiner Aufzeichnung(über Soundkarte) sehen
konnte.
Der Spuk lässt sich durch hinzufügen folgender Zeile ans Ende der PC-ISR
beheben:
1
ldi tmp, 0x02
2
out TIFR1, tmp
Schaut man 1000 Mal über den Code, so entdeckt man immer etwas neues!
julian
GELÖST!!!
Alles arbeitet so wie es soll, wenn ich alles fertig kommentiert hab,
stell ichs auf meine Seite und hier rein.
DANKE an EUCH, für die Tipps!
julian