Forum: Mikrocontroller und Digitale Elektronik AtMega8 und PWM - Erste Schritte


von Alexander G. (grossmann200)


Lesenswert?

Hallo,

nachdem ich das AVR-Tutorial und das Datenblatt vom ATmega8 dreimal 
gelesen habe, schaffe ich es immer noch nicht eine einfachste PWM auf 
den OC1A zu bringen. Nach dem Tutorial ist folgendes zu tun:

TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
TCCR1B = (1<<CS12) | (1<<CS10);
OCR1A = xxx;

Hier habe ich jetzt - für die Profis in diesem Forum wahrscheinlich 
lachhafte - Anfängerfragen:

1. Frage:
Als Anfänger versuche ich noch möglichst viel einzeln aufzuschlüsseln, 
dass heißt Zusammenfassungen zu vermeiden. Könnte man die erste Zeile 
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1) nicht auch wie folgt 
schreiben:

TCCR1A = TCCR1A | (1WGM11);
TCCR1A = TCCR1A | (1WGM10);
TCCR1A = TCCR1A | (1COM1A1);

2. Frage:
Mit der zweiten Zeile TCCR1B = (1<<CS12) | (1<<CS10) wird anscheinend 
die Zählgeschwindigkeit festgelegt, die laut Tutorial dann ein Teil von 
CK ist. Ist mit CK die Taktrate vom Mikrocontroller gemeint oder muss 
ich hier irgendwo noch einen Wert setzen?

3. Frage:
Ich habe obigen Tutorial-Code in ein Program eingebunden. Nach dem 
Datenblatt von meinem ATmega8 müssten die Bezeichnungen auch 
übereinstimmen. Jedoch ist im ATmega8-Datenblatt noch von einem WGM13 
die Rede. Ich vermute, dieser muss auf 0 gesetzt werden (was er 
wahrscheinlich schon ist). Um sicher zu gehen habe dennoch in mein 
Programm TCCR1B = TCCR1B & ~(1 << WGM13); eingefügt:

#include <avr/io.h>
void main(void)
{
TCCR1B = TCCR1B & ~(1 << WGM13);
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
TCCR1B = (1<<CS12) | (1<<CS10);
OCR1A = 10; //schon mit allen möglichen Werten experiementiert
while(1);
}

Ich glaube jedoch, es mir zu einfach zu machen. In vielen Forenbeiträgen 
werden irgendwelche Interrupts gesetzt oder Taktfrequenzen definiert 
etc. Eigentlich will ich nur eine LED an PB1 zum blinken bringen oder 
dimmen. Im nächsten Schritt schwebt mir vor die LED durch einen Stepper 
zu ersetzen.

Für Hinweise, was ich falsch gemacht habe bzw. was in dem Code noch 
alles ergänzt werden müsste, besten DANK!.

von Otto (Gast)


Lesenswert?

Hallo Alexander,

zu 1):

ist das selbe und bei einem "ODER" auch unproblematisch. Bei "UND" muß 
darauf geachtet werden, andere Bits nicht zu beeinflussen.

Die Definition von Taktfrequenzen dient i. A. dazu, von der Taktfrequenz 
abhängige Parameter richtig zu berechnen.

Der Interrupt ist m.E. in Deiner Anwendung nur nötig, um den Zähler 
(rechtzeitig) wieder (richtig) zu laden (reload).

Gruß Otto

von Karl H. (kbuchegg)


Lesenswert?

Alexander Grossmann wrote:

> #include <avr/io.h>
> void main(void)
> {
> TCCR1B = TCCR1B & ~(1 << WGM13);
> TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
> TCCR1B = (1<<CS12) | (1<<CS10);
> OCR1A = 10; //schon mit allen möglichen Werten experiementiert
> while(1);
> }
>
> Ich glaube jedoch, es mir zu einfach zu machen.

Das passt schon.
Das einzige was du vergessen hast, ist den OC1A Pin auch
auf Ausgang zu schalten :-)  Vergess ich auch immer wieder
gerne mal.

> In vielen Forenbeiträgen werden irgendwelche Interrupts gesetzt

Die brauchst du nur, wenn du auf spezielle Timerereignisse
per Programm reagieren musst. In deinem Fall macht aber
die Hardware die PWM ganz von alleine. Daher braucht es auch
keine ISR.

Setzte einfach den OC1A Pin auf Ausgang und erfreue dich
an deiner ersten blinkenden LED.

von Alexander G. (grossmann200)


Lesenswert?

Große Freude

super. Es funktioniert. Auch wenn ich nur die Zeile DDRB = DDRB | (1 << 
PB1); vergessen habe, ich hätte noch fünfmal das Datenblatt gelesen, 
gegoogelt etc. und wieder bis in die späte Nacht gegrübelt.

Danke Karl Heinz und Otto für die super Hilfe.

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.