Forum: Compiler & IDEs Fast-PWM auf ATmega88


von Olivier (Gast)


Lesenswert?

Hallo,

ich würde gerne exakt alle 5 Millisekunden auf einem Pin ein Signal 
ausgeben, welches etwa 100 Mikrosekunden breit ist. Zu diesem Zweck 
eignet sich theoretisch sehr gut der Timer1 im Fast-PWM mode. Laut 
Datasheet kann ich dafür z.B. für den Timer1 den mode 15 nehmen. Habe 
alles so gemacht wie im Datasheet beschrieben, doch es funktioniert 
einfach nicht. Benutze ich die Simulation im AVR-Studio, so geschieht so 
einiges was keinen Sinn macht, nur nicht die Funktionalität von mode 15. 
In der Simulation sehe ich deutlich dass der Mode 15 eingestellt ist, 
aber der TCNT1 zählt auch gerne mal wieder runter wie es im dual-slope 
üblich ist was aber nicht möglich sein sollte im mode 15. 
Compare-Matches werden generell ignoriert. Im folgenden der komplette 
Quelltext in C. Wo liegt der Fehler? Bin für Hilfe aus dem Forum sehr 
dankbar, da ich an diesem Punkt keine Lösung weiss. Beste Grüße,
Olivier

#include <avr/io.h>

int main()
{
//COM1A1: Clear OC1A (PB1) on Compare-Match, set OC1A (PB1) at BOTTOM
//WGM11, WGM10: Mode 15, FAST-PWM, OCR1A defines TOP

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


//WGM13, WGM12: Mode 15
//CS11: Prescaler to 8

TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11);


OCR1A = 200; //Defines TOP

ICR1 = 50; //Compare-Match

TCNT1 = 0; //Counter-Reset

DDRB |= (1<<PB1); //Enable OC1A for PWM-Output

for(;;);

return 0;
}

von Matthias (Gast)


Lesenswert?

...OCR1A = 200; //Defines TOP

ICR1 = 50; //Compare-Match

TCNT1 = 0; //Counter-Reset

DDRB |= (1<<PB1); //Enable OC1A for PWM-Output....

Das passt nicht:

ICR1 = 50; Compare Match ?????????????

Das glaube ich nicht! EIn Compare Match wird immer mit OCR1A/B 
generiert...

OCR1A = 200; //Defines TOP ????????
Der TOP-Wert ist meineswissen eher OCR1B oder ICP..

Musst du nochmal im Datenblatt lesen...

von Jörg X. (Gast)


Lesenswert?

@ Matthias (Gast):
Doch, die Register stimmen, der Mode 15 ist wohl so gedacht, falls man 
das (gepufferte) OCR1n Register im Betrieb  öfter verändern muss -- hier 
wäre mode 14 (ICR1 als TOP) wahrscheinlich angebrachter.
Der Duty-Cycle stimmt auf jeden Fall nicht (50/200 = 25% an) weil 
0.0001s/0.005s = 2% verlangt ist.
@OP:
Dass der Simulator merkwürdiges anzeigt, wenn du C-Code durchsteppst, 
ist dir hoffentlich klar: man kann kaum vorhersagen wie lange ein C 
Statement dauert und so entsteht der Eindruck vom Rückwärtslaufenden 
Timer (Wie bei drehenden Rädern, v.A. auf Video). Bei Hardware-einheiten 
ist dem Simulator nicht so recht zu trauen, also "in echt" ausprobieren!

hth. Jörg

von David H. (dafhit)


Lesenswert?

Hallo,
Gibt es da nicht einen Bug im AVR-Studio, dass simulieren mit PWM nicht 
geht?
Ich meine da wäre etwas gewesen.
Gruß
 David

von Johannes M. (johnny-m)


Lesenswert?

"16-bit Timer/Counters on all devices have several problems with PWM, 
prescaler and output compare. Output compare registers are not buffered 
properly."

(Zitat AVRStudio-Hilfe, Simulator, Known Issues)

von Olivier (Gast)


Lesenswert?

Zum Simulator:
Im Simulator läßt sich kein Fast-PWM-Mode einstellen, wohl aber z.B. der 
Mode 1, 2, 3 und auch mindestens ein CTC-Mode (Mode12).

Fast-PWM auf ATmega88:
Der Mode 15 (Datasheet P.132) funktioniert auf meinem ATmega88 nicht, 
wohl aber der Mode 14. So bleiben zwar die Doublebuffereigenschaften des 
Registers OCR1A ungenutzt, beim Verändern von ICR1 ist daher Vorsicht 
geboten so dass ICR1 immer >= TCNT1 ist.

Im folgenden der Quelltext, alle 5 Millisekunden wird ein 100 
Mikrosekunden breiter Puls ausgegeben, sofern der Controller mit 16 MHz 
getaktet wird:

--------------------------------------------------------------------
#include <avr/io.h>

int main()
{
TCCR1A |= (1<<WGM11);              //Mode 14, Fast-PWM
TCCR1B |= (1<<WGM13) | (1<<WGM12); //Mode 14, Fast-PWM
OCR1A = 200;                       //100 Mikrosekunden Puls
ICR1 = 10000;                      //Periodendauer 5 Millisekunden *1)
TCCR1A |= (1<<COM1A1);             //HIGH at BOTTOM, LOW at 
Compare-Match
TCNT1 = 0;                         //Timer Reset
TCCR1B |= (1<<PB1);                //Timer starten mit Prescaler = 8
DDRB |= (1<<PB1);                  //PWM-Output OC1A bzw. PB1 
freischalten
for(;;);
return 0;
}
--------------------------------------------------------------------

*1)
ICR1 kann nur im Fast-PWM-Mode beschrieben werden, deswegen muß zuerst
der Fast-PWM-Mode in den Registern TCCR1A und TCCR1B eingestellt werden.

Gruß Olivier

von Olivier (Gast)


Lesenswert?

Sorry, kleine Korrektur ist noch fällig:

Zyklus von 5 Millisekunden: ICR1 = 9999;
(0 bis 9999 => 10000 Counts)

Puls von 100 Mikrosekunden: OCR1A = 199;
(OC1A wird bei TCNT=BOTTOM=0000 gesetzt und
bei TCNT=200 wieder gelöscht, also im nächsten
Count nach dem Compare-Match)

von (Gast) == (Gast)


Angehängte Dateien:

Lesenswert?

Also auf einem M8 funktioniert Mode 15.

TCCR1A = 1<<COM1B1 ^ 1<<WGM11 ^ 1<<WGM10 ;
TCCR1B = 1<<WGM13 ^ 1<<WGM12 ^ 1<<CS10;
OCR1A=65535;   //TOP
OCR1B=32767;   //50%

Aber Achtung, echte 0% kriegt man nicht hin. Gut erkennbar bei kleinem 
TOP und nem Oszi.

Bsp. (s. Bild):
OCR1A=3;   //TOP
OCR1B=0;   //0%?

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.