Forum: Mikrocontroller und Digitale Elektronik AVR 8-Bit ATmega644 -> fast PWM Settings -> TCNT Register


von Martin Z. (mzenzes)


Lesenswert?

Hallo Forum,

ich habe eine recht spezielle Frage, und hoffe mir kann jemand die 
richtige Antwort geben.

Für ein bereits bestehendes Projekt bin ich gerade dabei den Quelltext 
(geschrieben in C) zu verstehen. Verbaut wurde der ATmega644 
Mikrokontroller. In meinem speziellen Fall befindet sich dann der Timer0 
im Fast-PWM-mode, und gibt eine variable Spannung heraus. So weit so 
unspektakulär.

Initialisiert wird der Kram mit folgendem Code-Fragment:
1
TCCR0B  = CK8;                                //TCCR=Timer/Counter Control Register
2
                                              //CK8=2 (definiert mit enum Anweisung)
3
                                              //timer prescaler: clk/8 (S 99)
4
TCCR0A  = (1<<COM0A1)|(1<<COM0B1)|3;          //die 3 für "11" in Bit0/Bit1
5
                                              //zusammen mit Bit2="0" von TCCR0B -> "011" -> "fast PWM" (S 99)
6
                                              //zusätzlich OC0A/B auf "non-inverting-mode"
7
OCR0A   = 0;                                  //vorläufiger Wert
8
OCR0B   = 120;                                //zweiter Offsetkerl wird fest "verdrahtet"
9
TCNT0   = (unsigned char)-TIMER_RELOAD_VALUE; //TIMER_RELOAD_VALUE=250;
10
                                              //Schreibend zugreifen? Sinn? Sollte aktueller Zählerstand sein
11
//OCR1  = 0x00;                               //sinn? war schon auskommentiert, irgendwas altes
Den Kommentar hab ich selbt hinzugefügt, hat also keinen Anspruch auf 
Korrektheit, ist nur um das für mich nachvollziehen zu können. Stolpern 
tu ich dann über folgende Zeile:
1
TCNT0   = (unsigned char)-TIMER_RELOAD_VALUE;
Der Wert von TIMER_RELOAD_VALUE ist in einer Header Datei per 
#define-Anweisung auf 250 definiert worden.

1. Warum wird schreibend auf das TimerCounter Register zugegriffen? Im 
Handbuch findet sich unter Punkt 13.9.3, S 101 der Entsprechende Passus, 
wo ein Write anscheinend nur den Counter neu setzt. Da bei mir dieser 
beim Init einmal beschrieben wird, ist das also herzlich unsinnig? 
Oder passiert dann intern irgendwas wichtiges, was sonst nicht passieren 
würde?

2. Eher C-bezogen: Was bedeutet dieses Casting auf "unsigned char" 
zusammen mit dem "-"? Wenn ich einen Integer auf char umwandle, entsteht 
doch das entsprechende ASCII-Zeichen?

3. Eher Elektrotechnisch bezogen: Die Fast-PWM-Frequenz ermittle ich 
dann laut Handbuch (S 93) durch
1
f_pwm=f_clk/(N*256) mit f_clk=20MHz und N=8
2
f_pwm=9.7kHz
Wenn ich nun mein PWM-Signal in PSpice herstellen wollen würde, müsste 
ich einfach ein Rechtecksignal (VPULSE) modellieren, das folgende 
Eigenschaften hätte:
1
V1=0V                //quasi GND
2
V2=5V                //VCC
3
TD=0s                //signal delay-time
4
TR=0s                //signal rise-time
5
TF=0s                //signal fall-time
6
PW=(OCRnX/256)*103µs //pulse-width, ermittelt durch aktuellen Registerwert
7
PER=103µs            //signal period, T=1/f
Jetzt müsste ich bei der Simulation natürlich meine zeitliche Auflösung 
entsprechend hoch genug ansetzten, dann erhielte ich ein "gutes" Abbild. 
Ist das so, oder habe ich irgendwo einen Gedankenfehler eingebaut?


Keine Standardfragen, geb ich gerne zu. Ich hoffe damit kommt jemand 
klar. Ansonsten erklär ich das gerne nochmal besser.

mit besten Grüßen
Martin Zenzes

PS:
Das Handbuch zum 644 als PDF findet sich zum Beispiel hier:
http://www.atmel.com/dyn/resources/prod_documents/doc2593.pdf

von Kai F. (kai-) Benutzerseite


Lesenswert?

das Statement
TCNT0   = (unsigned char)-TIMER_RELOAD_VALUE;
hat mich jetzt auch etwas verwirrt...
eigentlich macht das nichts anderes als den Timer auf den Wert 250 zu 
setzen. da ich nicht weiß, was das - macht, hab ich es einfach mal 
ausprobiert:
TCNT1 = (unsigned char)-250;
lcd_clear();
lcd_putint(TCNT1);
heraus kommt 6
frag mich bitte nicht wieso :P

von Johannes M. (johnny-m)


Lesenswert?

Kai Franke wrote:
> eigentlich macht das nichts anderes als den Timer auf den Wert 250 zu
> setzen. da ich nicht weiß, was das - macht, hab ich es einfach mal
> ausprobiert:
> [...]
> heraus kommt 6
> frag mich bitte nicht wieso :P
Das "-" macht, dass das Timer-Register nicht mit dem Wert 250, sondern 
mit dem Wert -250 geladen wird! Und die Zweierkomplement-Darstellung von 
-250 wird nach unsigned char konvertiert, damit sie in 8 Bit reinpasst 
und das Vorzeichenbit verschwindet. -250 in Zweierkomplement-Darstellung 
(int, 16 Bit) ist FF06, und davon nur die letzten 8 Bit gibt 0x06...

von Johannes M. (johnny-m)


Lesenswert?

Zu 1.: Ich halte das auf den ersten Blick auch für unsinnig. Das würde 
nur die Zeit bis zum ersten Überlauf auf 5 Timerzyklen verkürzen. Danach 
spielt es keine Rolle mehr.

von Kai F. (kai-) Benutzerseite


Lesenswert?

damit wäre das Mysterium schonmal geklärt, hat bestimmt auch einen Grund 
warum das so programmiert wurde ;)

von Steffen (Gast)


Lesenswert?

Vielleicht hat der Originalersteller der Software auch nur aus einem 
anderen Projekt kopiert. Und da es nur beim ersten mal einen Einfluss 
hat, ist es nie aufgefallen (sowas ist mir auch schon passiert).

Steffen.

von Martin Z. (mzenzes)


Lesenswert?

Jo, danke Jungs!

Damit ist 1. und 2. schonmal von meinem Zettel verschwunden.
Ich denke dann hat die Zeile wirklich keinen Sinn, vielleicht ein Relikt 
aus einer älteren Version.

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.