Forum: Mikrocontroller und Digitale Elektronik PWM Problem bei mega32


von AVR - neuling (Gast)


Lesenswert?

Grüße alle zusammen.

Ich hätte ein paar Fragen zum Atmel Mega 32, besónders im Zusammenhang 
mit der PWM funktion.
Ich habe bei mir zum dimmen von LED's die Timer initialisiert (Phase 
Correct Mode, kein Prescaler). Da ich im Datenblatt gelesen habe das man 
das DDRD (für Timer 1 und 2) auf Ausgang schalten muss habe ich die vier 
High bits auf 1 gesetzt (DDRD = 0xF0). Zur Kontrolle hab ich den 2ten 
Pin auch auf 1 gesetzt um zu überprüfen ob das funktioniert hat, und 
weil ich mir nicht sicher war ob 1 Ausgang ist oder umgekehrt.
Das Problem dabei: Egal wie ich das DDRD Register beschreibe, der 2te 
Pin ist immer High (3.3 Volt gemessen) und die Timer geben 0 aus. Ich 
hab dann auch mit dem Oszilloskop gemessen, um zu sehen ob ein Rechteck 
anliegt, was leider nicht der Fall ist.
Bei ~20mV Auflösung sieht man aber das Schwankungen vorhanden sind. 
(Haben aber nicht viel mit einem PWM Singal zu tun.)
Zum Schluss hab ich überprüft ob der 8te Pin etwas ausgeben kann (bei 
DDRD = 0xF0) Er kann ein High ausgeben.

Hat jemand eine Idee warum die Timer kein Signal ausgeben?

P.S.
Die Initialisierung:
1
void pwm_init(void)
2
{  
3
  //Timer 1:
4
  TCCR1A = ( (2<<COM1A0) | (1<<WGM10) | (2<<COM1B0) ); //8bit phase correct, 
5
  OCR1AL = 0xFF;//TOP ist über 8 bit modus eingestellt (0xFF)
6
  TCCR1B = ( (1<<CS10) |(1<<WGM10) ); //kein prescaler, 8bit
7
  OCR1BL = 0xF0;
8
  DDRD = 0xF0;
9
10
/*  //Timer 2 (ist für eine herkömmliche Lampe zuständig):
11
  TCCR2 = ( (1<<WGM20) | (2<<COM20) | (1<<CS20) );
12
  OCR2 = 0xFF;  */ zu test zwecken deaktiviert
13
14
}

von Karl H. (kbuchegg)


Lesenswert?

AVR - neuling wrote:

>   //Timer 1:
>   TCCR1A = ( (2<<COM1A0) | (1<<WGM10) | (2<<COM1B0) ); //8bit phase
> correct,

Warum schiebst du eine 2 nach COM1A0? Effektiv setzt du damit
das COM1A1 Bit. Anstelle eines 'toggels' hast du damit einen
'clear on compare match' programmiert.

        1 << COM1A0

wenn du allerdings tatsächlich das COM1A1 Bit setzten willst,
dann schreib das auch so hin:

        1 << COM1A1

Damit gibt es dann kein Missverständnis darüber, was du haben
willst, ob du das so haben willst oder ob du einfach nur einen
Programmierfehler gemacht hast.

>   OCR1AL = 0xFF;//TOP ist über 8 bit modus eingestellt (0xFF)

OCR1A ist ein 16 Bit Register. Atmel verlangt, dass die meisten
16 Bit Register (darunter auch OCR1A) beschrieben werden, indem
die Sequenz: 'zuerst das High Byte und erst dann das Low Byte'
eingehalten wird. Tust du das nicht, dann wird das Register
nicht verändert.
Dein Compiler weis darüber Bescheid und stellt dir ein
virtuelles 16 Bit Register OCR1A zur Verfügung. Beschreibe
es einfach und der Compiler kümmert sich um die korrekte
Sequenz.
Auch: Ich würde in das Compare Register mal einen Wert laden,
der nicht an den Extremwerten liegt, sondern genau in der Mitte.
Falls es irgendwelche Sonderfälle in der Werten gibt, dann treten
sie meistens bei den Extremwerte auf. Meide ich diese bei den
ersten Versuchen, dann habe ich meistes schon eine mögliche
Falle weg.
Um eine Analogie zu benutzen: Wenn ich eine Divisionsroutine
testen möchte, dann wird mein erster Versuch nicht gerade eine
Division durch 0 sein.

    OCR1A = 0x80;     // PWM auf 50%

>   TCCR1B = ( (1<<CS10) |(1<<WGM10) ); //kein prescaler, 8bit

das WGM10 Bit ist nicht im Register TCCR1B

>   OCR1BL = 0xF0;

gleiche Anmerkung wie für OCR1AL

von Andrej (Gast)


Lesenswert?

>>   (2<<COM1A0)  was soll das bezwecken? etwa bit COM1A1 setzen?(1 << COM1A1)
Das gleiche gilt für (2<<COM1B0)
Und was soll das:"TCCR1B = ( (1<<CS10) |(1<<WGM10) );" TCCR1B hat keinen 
WGM10
Vielleicht hast du richtigen Ansatz, aber das sind für mich kleine 
Fehler die stören den Sinn des Codes zu verstehen.
DDR schalten nur den Pin als Ausgang. Wenn der Timer richtig läuft, wird 
dann auch Ausgang angesteuert. Wenn du nur Ausgang ohne Timer prüfen 
willst, setze bzw. rücksetze PORT- Register.

von AVR - neuling (Gast)


Lesenswert?

Hab die Änderungen jetzt durchgeführt (das 16bit Register, die COM1B0 
hab ich das 2te bit gemeint).
Aber auch mit diesen Änderungen kommt kein PWM Signal an den Pin.

Ich hab das programm dann auch auf den Simulator durchlaufen lassen, und 
speziell das Port D beobachtet. Dabei musste ich feststellen das es ganz 
egal ist wie ich das DDRD Register beschreibe. Wenn ich einen pin 
händisch (also icht über den Timer) beschreibe ist er immer so wie ich 
den beschrieben habe. Aber: Das PWM Signal liegt nicht an PortD an. Beim 
Simulator ist dann ein PIND zu sehen (PortD Input soll das heißen glaub 
ich). Auf diesem Register werden die bits richtig gesetzt. Weiß jemand 
was ich machen kann damit das von diesem Register auch auf den Ausgang 
kommt?

von Falk B. (falk)


Lesenswert?

@ AVR - neuling (Gast)

>Hab die Änderungen jetzt durchgeführt (das 16bit Register, die COM1B0
>hab ich das 2te bit gemeint).
>Aber auch mit diesen Änderungen kommt kein PWM Signal an den Pin.

Probier mal den Code, der ist getestet und läuft.

Soft-PWM

MFG
Falk

von AVR - neuling (Gast)


Lesenswert?

Vielen Dank für die Hilfe.

Hab jetzt mit Hilfe des Links ein paar dinge in meinem Programm 
umgeschrieben, und nun funktioniert es.

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.