Ich nutze im Moment einen Mega88 und versuche mich mit den PWM Modi
vertraut zu machen.
Kann es sein dass der Simulator total falsch simuliert bei solchen
Sachen? Wenn ich den Fast PWM nutze zählt der Zähler im Simulator bis
zum TOP Wert und dann wieder zurück. Eigentlich dürfte er ja immer nur
hoch zählen. Wenn ich mein Programm in den Baustein schreibe und mir das
Ergebnis mit dem Oszi ansehe, scheint es aber genauso zu stimmen wie es
im Datenblatt beschrieben ist und nicht so wie es der Simulator anzeigt.
Was ich aber teilweise nicht verstehe: In welchem Modus kann ich welche
OCx Pins nutzen um ein PWM Signal abzugreifen und mit welchen Registern
muss ich den MAX Wert und den Compare Wert einstellen? Das Beispiel im
Tutorial mit Fast PWM, ICR1 als MAX Wert und OC1A als Vergleichswert
funktioniert. Jedoch kann ich scheinbar OC1B nicht als zweites PWM
Signal nutzen, warum? Ist das wirklich so?
Und was geschieht wenn ich WGM13:0 = 15 setze, also in den Modus wo der
Zähler bis zum OCR1A Wert zählt, wo kommt dann der Vergleichswert hin?
Und wo kann ich ein PWM Signal abgreifen?
Irgendwie wäre da mal so etwas wie eine Matrix fürs Tutorial nicht
schlecht wo die Modi gelistet sind mit Untermodi und dann Spalten "wo
kommt das Signal raus", "wo wird der Vergleichswert hingeschrieben",
"welche Pins sind nutzbar".
Hi,
im Datenblatt ist Tabelle 14-4 (Seite 132) eigentlich sehr
aussagekräftig !
Stephan S. wrote:
> Ich nutze im Moment einen Mega88 und versuche mich mit den PWM Modi> vertraut zu machen.
Fein.
> Kann es sein dass der Simulator total falsch simuliert bei solchen> Sachen? Wenn ich den Fast PWM nutze zählt der Zähler im Simulator bis> zum TOP Wert und dann wieder zurück. Eigentlich dürfte er ja immer nur> hoch zählen. Wenn ich mein Programm in den Baustein schreibe und mir das> Ergebnis mit dem Oszi ansehe, scheint es aber genauso zu stimmen wie es> im Datenblatt beschrieben ist und nicht so wie es der Simulator anzeigt.
Der Simulator macht das manchmal seltsame Sachen. Also nicht darauf
verlassen !
> Was ich aber teilweise nicht verstehe: In welchem Modus kann ich welche> OCx Pins nutzen um ein PWM Signal abzugreifen und mit welchen Registern> muss ich den MAX Wert und den Compare Wert einstellen? Das Beispiel im> Tutorial mit Fast PWM, ICR1 als MAX Wert und OC1A als Vergleichswert> funktioniert. Jedoch kann ich scheinbar OC1B nicht als zweites PWM> Signal nutzen, warum? Ist das wirklich so?
Siehe Tabelle 14-4 (s.o.). Bei FastPWM Mode 14 kannst du den MAX Wert
über OCR1 einstellen und OC1A und OC1B nutzen! Das geht auf alle Fälle!
Hier nen kleines Beispiel für die Konfiguration:
// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (clear)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
oder mit Interrupts:
// Timer 1 overflow ISR
ISR (TIMER1_OVF_vect)
{
}
// Timer 1 compare A ISR
ISR (TIMER1_COMPA_vect)
{
}
// Timer 1 compare B ISR
ISR (TIMER1_COMPB_vect)
{
}
// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (clear)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
TIMSK |= (1 << TOIE1) | (1 << OCIE1A) | (1 << OCIE1B);
> Und was geschieht wenn ich WGM13:0 = 15 setze, also in den Modus wo der> Zähler bis zum OCR1A Wert zählt, wo kommt dann der Vergleichswert hin?> Und wo kann ich ein PWM Signal abgreifen?
In dem Modus kannst Du nur noch OC1B als PWM Kanal nutzen ! Raus kommts
dann an PB2 (OC1B)
>> Irgendwie wäre da mal so etwas wie eine Matrix fürs Tutorial nicht> schlecht wo die Modi gelistet sind mit Untermodi und dann Spalten "wo> kommt das Signal raus", "wo wird der Vergleichswert hingeschrieben",> "welche Pins sind nutzbar".
siehe Tabelle !
Grüße,
Michael
Hab hierfür mal nen Codegenerator geschrieben für Mega 8, 16, 32
Beitrag "Codegenerator Timer1 für Mega 8, 16, 32"
für Mega88 musst die Registernamen wahrscheinlich ein wenig anpassen !
Grüße,
Michael
Vielen Dank! Da hab ich den Wald vor lauter Bäumen mal wieder nicht
gesehen. Wenn ich natürlich die COM1B nicht konfiguriere kommt
logischerweise auch nichts raus, auch wenn ich PB2 auf Ausgang schalte.
In welchem Datenblatt soll die besagte Tabelle eigentlich sein? In
meinem mega88 Datenblatt 09/07 kann ich weder bei dem genannten Bild,
noch auf genannter Seite sowas finden.
Den Generator find ich übrigens echt gut. Wenn da jetzt noch stehen
würde welche Ausgänge nutzbar sind und in welche Register ich die
Vergleichswerte schreiben müsste wäre er perfekt!
Grund für die Ganze Aktion ist übrigens net konkrekte Aufgabenstellung:
Ich brauche 2 PWM-Signale. Das zweite ist genau invertiert zum ersten.
Das Problem an der Sache ist allerdings dass ich eine einstellbare
Totzeit brauche, sprich wenn das erste Signal low geht soll das andere
nicht sofort auf high gehen, sondern erst nach einer definierbaren Zeit.
Dazu hab ich bis jetzt noch keine so einfache Lösung gefunden.
Hallo Stephan,
in diesem Datenblatt:
http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf
ists Seite 133 Tabelle 15-4 (sorry hatte geschrieben 14-4 da mein
Datenblatt ein wenig älter 11/06).
> Den Generator find ich übrigens echt gut. Wenn da jetzt noch stehen> würde welche Ausgänge nutzbar sind und in welche Register ich die> Vergleichswerte schreiben müsste wäre er perfekt!
Danke. Nutzbar sind natürlich die Ausgänge die Du konfigurierst. Also in
Deinem Beispiel OC1A und OC1B. Welche Pins das sind sagt uns das
Datenblatt. In Deinem Falle also PB1 und PB2. Für den Pin OC1A (PB1) ist
das Register OCR1A zuständig und für Pin OC1B (PB2) eben OCR1B.
> Ich brauche 2 PWM-Signale. Das zweite ist genau invertiert zum ersten.
Fein Timer 1 hat genau 2 "Ausgangspins". Die Invertierung kannst auch
schon "reinbauen". Je nach dem wie Du COM1A1/COM1A0 bzw. COM1B1/COM1B0
setzt.
> Das Problem an der Sache ist allerdings dass ich eine einstellbare> Totzeit brauche, sprich wenn das erste Signal low geht soll das andere> nicht sofort auf high gehen, sondern erst nach einer definierbaren Zeit.> Dazu hab ich bis jetzt noch keine so einfache Lösung gefunden.
Das klingt nicht zu wild.
Ich habs so verstanden:
Kanal A:
1
_______ ___
2
__| |_________________|
3
4
xxxx
5
__ ____________
6
|___________| |___
Kanal B:
Der Bereich markiert mit den xxxx ist der Totzeitbereich. Kanal A ist
high und Kanal B soll nach Kanal A + Totzeit auf high gehen. Richtig ?
Kannst Du folgendermassen machen:
OCR1A bestimmt das Tastverhältnis für Kanal A, Bsp. Wert = 200
OCR1B bestimmt das Tastverhältnis für Kanal B, und kann einfach
berechnet werden, mit OCR1B = Totzeitwert + OCR1A. Musst nur darauf
achten, dass der Wert von OCR1B nicht größer als ICR1 wird !
Grüße,
Michael
So in etwa wars richtig, nur dass ich bei beiden Wechseln die Totzeit
brauche. Eigentlich dachte ich auch dass ich jetzt die Lösung habe, aber
irgendwas haut nicht bei der Berechnung hin. Folgendermaßen sieht mein
Programm aus:
#include <avr/io.h>
#define TCLK 0.0000001
int main()
{
uint16_t f=10000;
uint16_t t_tot=0;
ICR1 = 1/(f*2*TCLK);
OCR1A = ((ICR1)/2) - (t_tot/(2*TCLK));
// OC1A und OC1B auf Ausgang
DDRB = (1 << PB1 ) | (1 << PB2 );
// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (set)
TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1) | (1 << COM1B0);
TCCR1B = (1 << WGM13) | (1 << CS10);
OCR1B = (ICR1 - OCR1A);
while( 1 )
;
}
Jetzt gibts folgendes Problem:
Bei "ICR1 = 1/(f*2*TCLK);" kommt wenn f gleich 10000 ist nicht 500,
sondern fälschlicherweise 499 raus. bei f gleich 1000 und f gleich
100000 ist das Ergebnis richtig. Ich kann es nicht nachvollziehen was da
passiert. Rundungsfehler?