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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.