Hi,
ich möchte ein IR-Signal gem. Anhang erzeugen, wobei die Trägerfrequenz
40 kHz betragen soll. D. h. für die im Anhang angegebenen Zeiten soll
der Träger eben entsprechen an- bzw. ausgeschaltet werden.
Das ganze möchte ich mit einem ATmega8 (8 MHz) erzeugen und mein
bisheriger Ansatz ist, dass ich Timer 2 genommen habe, um die 40 kHz zu
erzeugen => kein Problem. Ferner möchte ich nun noch Timer 1 benutzen,
um die Zeiten für die Schaltdauer zu generieren. Und genau da ist mein
Problem, ich kriege es einfach nicht hin.
Wollte einfach mal generell fragen, ob das so der geeignete Ansatz ist.
Denn erschwerend kommt noch dazu, dass es möglichst universell sein
soll. D. h. es wäre wünschenswert, dass die Zeiten z. B. in Vielfachen
von 10µs in einem Array liegen, dass ich dann einfach durchlaufen kann.
Oder gibt es bessere Ideen?
Gruß
Thomas
Alle Deine Verzögerungen passen in das 16-Bit-Raster des Timer1.
Lass Timer1 mit 1MHz klappern und nutze einen Compare-Interrupt.
In dessen ISR
- holst Du das nächste Intervall aus dem Array und addierst es auf den
aktuellen Compare-Wert auf (OCR1A einlesen, Intervall dazu addieren,
Ergebnis in OCR1A zurückschreiben), um den Termin für den nächsten
Int zu setzen,
- erhöhst Du einen Zähler, um anhand seines Bit 0 festzustellen, ob
jetzt Signal oder Pause ausgegeben wird. Bei Signal koppelst Du den
OCR-Pin von Timer2 an Timer2 an (40kHz wird ausgegeben), bei Pause
schaltest Du den OCR-Pin als normalen Ausgang, der auf L liegt.
Das alles findet in der ISR statt und verbraucht weniger als 1%
Rechenleistung. Dein Mega8 kann also noch viele andere Dinge nebenher
erledigen...
...
Hallo Hannes,
vielen Dank für deine Antwort, ich komme der Sache langsam näher :)
Mein Fehler war, dass ich den CTC-Mode benutzt habe, welcher ja den
Zählerstand bei jedem Match wieder nullt. Außerdem bin ich nicht auf die
einfach Sache gekommen, einfach aufzuaddieren.
Hier mal auszugsweise mein Code:
Nochmal die Rahmenbedingungen: AVR läuft mit 8MHz, Prescaler für Timer1
ist /8, der für Timer2 /1. Ich lasse mir bei jedem Compare-Interrupt PB0
toggeln.
Warum messe ich eine Frequenz von 500Hz an PB0? Bei jedem Interrupt
addiere ich doch 8000 dazu, wegen des Prescalers kommt der nächste
Interrup dann quasi 8*8000=64000 Take später, ein toggeln müsste doch so
alle (1/8MHz)*64000=8ms erfolgen, oder nicht?
Thomas
> Nochmal die Rahmenbedingungen: AVR läuft mit 8MHz, Prescaler für Timer1> ist /8,
Das ist gut, der Timer1 läuft daher mit 1 MHz.
> der für Timer2 /1.
Der spielt jetzt noch keine Rolle, da Du ja erstmal nur PB0 toggelst.
> Ich lasse mir bei jedem Compare-Interrupt PB0> toggeln.
Richtig, zum Test...
> Warum messe ich eine Frequenz von 500Hz an PB0? Bei jedem Interrupt> addiere ich doch 8000 dazu, wegen des Prescalers kommt der nächste> Interrup dann quasi 8*8000=64000 Take später, ein toggeln müsste doch so> alle (1/8MHz)*64000=8ms erfolgen, oder nicht?
8 MHz und Vorteiler 8 kürzen sich raus, man kann mit 1 MHz Timerztakt
rechnen, ein Timerwert entspricht also einer Mikrosekunde.
Demnach toggelst Du alle 8 Millisekunden, bekommst eine Periode von 16
ms, das entspricht einer Frequenz von 62,5 Hz.
Wenn Du etwas Anderes misst, dann macht Dein Code nicht das, was Du von
ihm erwartest. Da kann ich Dir aber nicht helfen, C ist nicht mein Ding,
ich werkele in Assembler.
...
Hi,
>wenn Du etwas Anderes misst, dann macht Dein Code nicht das, was Du>von ihm erwartest.
Du hast Recht, lag aber an meiner Dummheit. Ich hatte noch eine Zeile
zum stoppen von Timer 2 drin, und die hat ein Bit von Timer 1 verändert,
daher das verhalten.
Jetzt funktioniert alles.
Vielen Dank, Hannes!
Thomas