Hallo, jetzt sind die Hardwarespezialisten gefragt. In einem Programm
habe ich (verzweifelt) gesucht, warum beim Umkonfigurieren des Timers
kein CTC-Ton kommt. Beim Experimentieren ist mir dann etwas total
seltsames aufgefallen, dieses Phänomen hab ich nicht so direkt aus dem
Datenblatt herausgelesen?
Ist hier wirklich ein Designfehler im Atmega oder habe ich einen
Denkfehler!
Langsam zum Mitdenken
Folgendes Miniprogramm:
1
$regfile = "m644def.dat"
2
$crystal = 8000000
3
Ddrd.5 = 1 'OC1A als Output
4
Tccr1a = &B01000000 'CTC Pin D5=OC1A, CTC-Mode
5
Tccr1b = &B00011101 'CTC bei ICR1 statt OCR1A
6
Icr1l = 4 '4=781,25 Hertz
7
Ocr1al = 0
CTC-Modus 12, TOP=ICR1, die high-Bytes sind in jedem Register 0.
Das ergibt eine Frequenz von 1/(2*1024*(1+4))=781,25 Hertz
Passt auch alles und stimmt. Durch Ändern von Icr1l ändert sich auch die
Frequenz.
Was aber nicht hervorgeht ist, dass plötzlich auch Ocr1al den CTC-Modus
beeinflusst. Durch Experimentieren habe ich herausgefunden, dass
folgendes gelten muss: Ocr1a1<=Icr1l, sonst wird der Ton einfach
abgeschaltet.
Warum? Steht nicht so im Datenblatt!!
The Output Compare Registers contain a 16-bit value that is continuously
compared with the counter value (TCNTn). A match can be used to generate
an Output Compare interrupt, or to generate a waveform output on the
OCnx pin.
Es bleibt aber unklar, ob dieser Match auch beim frequenzbestimmtenden
Umschaltens des CTC auf Icr1l so gelten soll oder ob es nicht doch ein
Designfehler ist
Hmm... leider bin ich grad nicht zu Hause, aber am Montag werde ich das
mal nachprüfen...
Wenn bis dahin noch keine Antwort gekommen ist, sag ich dir, was bei mir
rauskam...
Du hast COM1A[1:0] = 0b01 eingeschaltet, also "Toggle OCnA/OCnB on
Compare Match."
Wenn du nun OCR1A einen Wert zuweist, bei dem nie mehr ein
compare match auftreten kann (weil er oberhalb von TOP liegt), wie
soll da dann noch etwas umschalten am Ausgang OC1A?
Jörg Wunsch schrieb:> Du hast COM1A[1:0] = 0b01 eingeschaltet, also "Toggle OCnA/OCnB on> Compare Match.">> Wenn du nun OCR1A einen Wert zuweist, bei dem nie mehr ein> compare match auftreten kann (weil er oberhalb von TOP liegt), wie> soll da dann noch etwas umschalten am Ausgang OC1A?
Ja, schon - aber andererseits steht im Datenblatt:
In Clear Timer on Compare or CTC mode (WGMn3:0 = 4 or 12), the OCRnA or
ICRn Register are used to manipulate the counter resolution. In CTC mode
the counter is cleared to zero when the counter value (TCNTn) matches
either the OCRnA (WGMn3:0 = 4) or the ICRn (WGMn3:0 =12). The OCRnA or
ICRn define the top value for the counter, hence also its resolution.
This mode allows greater control of the compare match output frequency.
It also simplifies the operation of counting external events.
Steht doch klar "entweder OCRnA oder ICRn", ich hab hier Modus
(WGMn3:0=12) eingeschaltet, dass dann aber zusätzlich zum
frequenzbestimmenden ICRn noch OCRnA quasi als Portschalter dazukommt,
geht da nicht so klar hervor..
Figure 14.1 auf Seite 107 scheint etwas mehr Klarheit zu bringen: es
muss der Counter offensichtlich einmal OCRnA erreichen und dann
zusätzlich noch ICRn den Topvalue erreichen, damit am Ausgangsport
getoggelt wird. Also muss OCRnA immer unterhalb oder gleich zum Topwert
von ICRn liegen..
Naja, Bilder sagen mehr als 1000 Worte... gilt wohl auch für das Atmega
Datenblatt - hab ich das Bild richtig interpretiert?
Manfred S. schrieb:> In CTC mode> the counter is cleared to zero when the counter value (TCNTn) matches> either the OCRnA (WGMn3:0 = 4) or the ICRn (WGMn3:0 =12). The OCRnA or> ICRn define the top value for the counter, hence also its resolution.
Machen sie ja auch. Aber das interessiert dich ja gar nicht: dich
interessiert das Umschalten des Ausgangs OCR1A, und der schaltet
natürlich nur um, wenn er auch zum Zug kommt. Wenn du den Timer
durch einen kleineren Wert von ICR1 bereits wieder rücksetzen
lässt, dann steht dein OC1A-Ausgang im Regen und schaltet nicht mehr.
Der von dir gewählte Modus ist also eher wenig sinnvoll für den von
dir gewünschten Anwendungszweck. (Naja, oder vielleicht doch, aber
dann sollte man ICR1 auf 0xffff lassen, damit es nie in die Verlegen-
heit kommt, den TOP-Wert zu definieren.)
Danke Jörg,
ist einleuchtend.
Ich hatte nur folgendes programmiert:
Timer0 liest im 4kHz Takt Sprachbytes ein und gibt sie über fast PCM,
Timer1, OCR1AL, Teiler 1 aus (z.B. Wort eins). Hie und da wollte ich
dann Beeptöne ausgeben. Daher meine Idee:
lass die Sprachbytes weiterhin über OCR1AL durchrennen, dann habe ich
eine wunderbare Zeitschlefe (ob das Wort eins gesagt wird oder ein
Beepton gleicher Länge kommt ist ja egal) - ich schalte vorher den
Timer1 auf CTC, Mode 12 /Teiler 1024 und ICR1 auf 4. Da die Sprachbytes
dezimal so zwischen 50-150 liegen und im 4khZ Rhythmus an OCR1AL
durchgereicht wurden, ist der Ausgang stumm geblieben... das zu finden
war nicht leicht.
Habs jetzt mit einem Flag für Beepton in der 4kHz Schleife gelöst: lies
weiterhin die Sprachbytes ein, gib Sie aber nicht zu OCR1AL aus, sondern
fixiere zu Beginn OCR1AL mit 0 und ICR1 mit der gewünschten Frequenz
(z.B. 4) - geht
Damit hat aber ICR1 auch keinen Sinn mehr für meine Anwendung: hab daher
Modus CTC 4 gewählt und setze einfach zu Beginn der Zeitschleife OCR1AL
auf 4 und ignoriere die eingelesenen Bytes - funktioniert perfekt
Und ich hab wieder jede Menge über die interne Struktur des Timers
gelernt - nochmals vielen Dank für die entscheidenden Hilfestellungen -
ist ein total faszinierendes Hobby und mit der perfekten Unterstützung
hier wirds noch spannender.