Forum: Mikrocontroller und Digitale Elektronik Atmega32 Timer1 OCR1A künstlich auslösen


von Jalu (Gast)


Lesenswert?

Timer 1, Mode 0 (Normal Mode).

Wie löse ich sicher und schnell auf Wunsch einen CompA Interrupt aus?
OCR1A = TCNT1+1
macht es ja offensichtlich nicht. Offensichtlich ist da der Timer schon 
weiter. Auch +5 reicht noch nicht.

OCR1A = TCNT1+10 geht dagegen.

Aber da muss es doch eine bessere Methode geben?

von spess53 (Gast)


Lesenswert?

Hi

>Aber da muss es doch eine bessere Methode geben?

FOC1A in GTCCR setzen.

MfG Spess

von Jalu (Gast)


Lesenswert?

Spess, danke, aber es gibt keinen GTCCR im Atmega32.

Es gibt einen FOC1A im TCCR1A. Den hab ich schon probiert - der 
beinflusst zwar den WaveForm Generator, aber löst keinen Interrupt aus. 
Oder verstehe ich da etwas nicht richtig?

Grüsse

von spess53 (Gast)


Lesenswert?

Hi

>Es gibt einen FOC1A im TCCR1A. Den hab ich schon probiert - der
>beinflusst zwar den WaveForm Generator, aber löst keinen Interrupt aus.
>Oder verstehe ich da etwas nicht richtig?

Entschuldige ich hatte das falsche Datenblatt erwischt.
Was willst du denn machen? Die Interruptroutine ausführen?

MfG Spess

von H.Joachim S. (crazyhorse)


Lesenswert?

Das Bit lässt sich per Software nur löschen (durch schreiben einer 1), 
nicht setzen.
Falls es keine Rolle spielt, dass der Timerstand verändert wird:
TCNT1=OCR1A;

müsste eigentlich immer funktionieren. Nicht schön, zugegeben.

von spess53 (Gast)


Lesenswert?

Hi

>Das Bit lässt sich per Software nur löschen (durch schreiben einer 1),

Welches?

MfG Spess

von Jalu (Gast)


Lesenswert?

Ich möchte ein bestimmtes Protokoll mit einem definierten Timing 
erzeugen auf einem Bus. Ich lasse jetzt mal einige Infos weg, sonst 
wirds zu lang:

In Kürze: Ein Startbit wird benötigt. Dies ist immer null.

1) Dazu setze ich die OC1A auf low (also den Ausgang auf low), setze den 
OCR1A auf TCNT+6 (ab 6 gehts).
2) Dann geht der uC ab in die ISR, dort wird OCR1A auf den Ablaufwert 
für das null-bit gesetzt (34us) und der Ausgang OC1A auf high 
konfiguriert, so dass er nach den 34us wieder high ist.

Diese 34us werden in der ISR umgeschaltet auf andere Zeiten, daher 
dieser Ansatz. Hat jetzt aber mit dem Problem nichts zu tun.

Dieses OCR1A = TCNT+6 scheint einfach unelegant, da von der Laufzeit 
abhängig. Offensichtlich muss man dem OCR1A 6 Takte Vorlauf geben, damit 
der Timer den Befehl nicht 'überholt'.

Daher die Überlegung, dass es da (ähnlich FOC1) etwas besseres geben 
müsste - eigentlich.

Grüsse

von H.Joachim S. (crazyhorse)


Lesenswert?

TIFR.OCF1A

von Jalu (Gast)


Lesenswert?

@Joachim - spielt leider eine Rolle. Es läuft auch noch ein Capture-ISR 
und ein Lese-ISR auf CompB, zum Lesen vom Bus und zur Konflikterkennung 
(CSMA). Dafür brauche ich (glaube ich) den Timerstand.

von H.Joachim S. (crazyhorse)


Lesenswert?

hm...
bliebe noch die "brutale" Methode:

#asm ("cli")
#asm ("rcall  timer1_compa_isr")

Auch nicht das, was den smarten Programmierer zum Jubeln bringt...

von Jalu (Gast)


Lesenswert?

Korrekt. TIFR.OCF1A lässt sich leider nicht zum auslösen des Interrupts 
verwenden.

Ich glaube fast langsam, es geht einfach nicht. OCR1A = 
TCNT+<Laufzeit-Delta> scheint nötig. Das scheinen die 6 Takte zu sein.

Das unschöne ist, diese 6 Takte führen dann zusammen mit dem Overhead 
des ISR zu ca einer us verlängerter 0-Zeit beim ersten Aufruf. Kann man 
zwar wegkorrigieren, aber suche noch nach einer eleganteren Lösung.

Im Grunde modifizierte ich hier Peter Danneggers suart Lösung. Er umgeht 
das Problem, indem er halt einfach eine unbestimmte Zeit wartet, bis der 
Timer auslöst und macht dann auch das Startbit im Timer. Diese 
unbestimmte Zeit ist aber in meinem Fall wieder störend.

von Jalu (Gast)


Lesenswert?

Hmm, ja - zumindest ein interessanter Ansatz.

Danke Euch einmal soweit. Jetzt gehts erstmal ins Bett. Mal sehen was 
morgen noch so an Ideen reintrudeln mag.

Grüsse

von Peter D. (peda)


Lesenswert?

Jalu schrieb:
> Im Grunde modifizierte ich hier Peter Danneggers suart Lösung. Er umgeht
> das Problem, indem er halt einfach eine unbestimmte Zeit wartet, bis der
> Timer auslöst und macht dann auch das Startbit im Timer.

Es wird immer mit der Bitzeit synchronisiert, wie bei einer HW-UART 
auch.
Wenn man die Bytes hintereinander sendet, wird garnicht gewartet, d.h. 
das nächste Startbit kommt genau hinter das vorherige Stopbit.


Peter

von H.Joachim S. (crazyhorse)


Lesenswert?

Hm, da stecke ich nicht drin, keine Ahnung. Kann sein, dass das alles 
gar kein Problem ist
Obige Lösung würde jedenfalls funktionieren. Könnte natürlich passieren, 
dass in der Zeit tatsächlich ein OCR1A-Ereignis eingetreten ist (und 
damit direkt nach reti erneut ein dann ungewollter Interrupt ausgelöst 
wird). Wenn du das behandelst, dürfte das Vorgehen sauber sein.

von Jalu (Gast)


Lesenswert?

@Peter,
ja, von bit zu bit schon.

Was ich meinte, war der Start. Da kann es ja unterschiedlich lange 
dauern, bis der Transfer anspringt. Du wirst sagen, na und. Ich habe vor 
dem Startbit eine bestimmte Anzahl von Bitzeiten, die der Bus frei sein 
muss, bevor ich anfangen darf zu senden. D.h. es ist einfacher, mit 
einem OCR1A Interrupt zu beginnen, da ich dann direkt nach diesem 
Vorlauf von x Bitzeiten in die TX Routine springen kann und nur einen 
minimalen und definierten Zeitversatz habe.

Grüsse



PS: Nun gut, Du wirst jetzt vermutlich weiterhin sagen, diesen Vorlauf 
auch in der gleichen ISR Routine abzuwickeln - dieser Gedanke kommt mir 
gerade. Dann ist 'Vorlauf' und 'Senden' perfekt syncronisiert. Könnte 
man ja von einem 'State' abhängig machen und in einer Switch-Anweisung 
abhandeln. Mal sehen.

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
Noch kein Account? Hier anmelden.