Liebes Forum, ich benötige für eine Versuchsschaltung ein PWM Signal, bei dem nicht nur der Dutycycle (t_on/T) sondern auch die Länge der PWM Periode T im Programmablauf dynamisch verändert werden kann. Leider funktioniert unten angehängter Codeschnipsel nur für T=ICR1=const, sobald ich ICR1 im Programm ändere, gibt es Aussetzer im PWM Signal, also mache ich irgendetwas falsch (Wertebereichsüberscheitung für ICR1 habe ich bereits ausgeschlossen). Und ich kann mich nicht mehr erinnern, wie ich das damals programmiert habe. Könnt Ihr mir auf die Sprünge helfen? Gibt es vielleicht etwas Fertiges, dass ich übernehmen und anpassen kann? Der Code ist im Arduinostyle, die Funktion setup(){} wird nur einmal ausgeführt, loop(){} endlos, PWM Takt=T ist ca. zwischen 4us und 200us: .... volatile int Set_TCNT3L; // Variable zum Setzen des Registers TCNT3L volatile int Set_TCNT3H; // Variable zum Setzen des Registers TCNT3H ISR(TIMER3_OVF_vect) { TCNT3H = Set_TCNT3H; TCNT3L = Set_TCNT3L; }; void setup() { cli(); TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11); TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); TCCR3A = 0; TCCR3B = 2; TIMSK3 = (1 << TOIE3); // enable TCNT3 overflow sei(); ICR1 = 200; //Periodenlänge T der PWM, 16Bit Register, default-Wert, 100=160Khz, 200=80kHz OCR1A = wert_von_OCR1A; // On-Zeit t1 der PWM, 16 Bit Register, default-Wert Set_TCNT3H = 255; //Setze H-Byte zuerst Set_TCNT3L = 0x00; } void loop() { // Berechnung von t_on und T t_on = int(irgendeinefunnktion()); t_off = int(eineandereFunktion()); T = t_on + t_off; ICR1 = T; // Setzen der Register ICR1 bestimmt T OCR1A = t_off; // OCR1A bestimmt t_off }
PWMBastler schrieb: > T=ICR1=const, sobald ich ICR1 im Programm ändere Wenn TCNT schon grösser ist als dein neues ICR, dann läuft der Timer bis MAX, um erst im nächsten Durchlauf das neue ICR als MAX zu akzeptieren. Du darfst ICR also nur setzen, solange TCNT < ICR. Ein geeignter Ort fürs Setzen von ICR wäre z.B. die Timer-Overflow Routine, denn dort ist TCNT sehr niedrig. Leider schreibst du ja nicht, welcher MC denn nun benutzt wird, weitere Tipps sind also erstmal nicht möglich. PWMBastler schrieb: > volatile int Set_TCNT3L; // Variable zum Setzen des Registers TCNT3L > volatile int Set_TCNT3H; // Variable zum Setzen des Registers TCNT3H int ist hier nicht der richtige Datentyp. Entweder setzt du TCNT3 zusammen als int, oder jede Hälfte des Timers mit z.B. uint8_t. Das ist nämlich mit GCC erlaubt:
1 | TCNT3 = meinintwert; |
Um die Bytereihenfolge kümmert sich der Compiler.
:
Bearbeitet durch User
Matthias S. schrieb: > Wenn TCNT schon grösser ist als dein neues ICR, dann läuft der Timer bis > MAX, um erst im nächsten Durchlauf das neue ICR als MAX zu akzeptieren. > Du darfst ICR also nur setzen, solange TCNT < ICR. > Ein geeignter Ort fürs Setzen von ICR wäre z.B. die Timer-Overflow > Routine, denn dort ist TCNT sehr niedrig. > Leider schreibst du ja nicht, welcher MC denn nun benutzt wird, weitere > Tipps sind also erstmal nicht möglich. Aha! okay, ich werde das gleich mal prüfen! Es ist ein atmega32U4 mit 16MHz Feedback nach dem Test, PWMBastler
> Leider schreibst du ja nicht, welcher MC denn nun benutzt wird Der Titel des Threads lautet: > atmega32: Wie ging gleich nochmal PWM mit veränderlichem T > Es ist ein atmega32U4 mit 16MHz Aber hallo, zwischen ATmega32 und ATmega32u4 gibt es große Unterschiede! Warum hast du das nicht gleicht im Eröffnungs-Thread geschrieben?
Hallo Stephan, mist das mit dem Atmega32 != atmega32u4, tut mir leid, dass ich mich so unklar ausgedrückt habe. Danke an Matthias, ich versuche mich mal im Reengeneering, weil ich meinen Code nicht mehr verstehe, ich benutze dazu http://www.avrbeginners.net/architecture/timers/timers.html, Abschnitt "PWM Mode" und das Data Sheet atmega32u4 Register TCCR1A: COM1A1, COM1A0 und WGM11 sind gesetzt, was bedeutet das? COM1A0 ist bit 7 COM1A1 ist bit 6 wenn beide gesetzt sind, dann bedeutet das "noninverting PWM" WGM11 ist bit 1 Das bedeutet, dass der PWM Takt eine Auflösung von 9-Bit hat Register TCCR1B: WGM13, WGM12 und CS10 sind gesetzt. WGM13 ist bit 4 WMG12 ist bit 3 --> bit 4 und bit 3 gesetzt = Mode 12=CTC Mode= Clear Timer on Compare Mode CS10 ist bit 1 --> Prescaler = 1 TCNT1 scheint ein Counter zu sein, der hoch zählt. Wenn er den Wert von OCR1A erreicht hat, wird er zu null gesetzt, okay, das muß dann wohl die off-Zeit bestimmen. Wie ICR1 das mit rein spielt, ist mir leider nicht klar geworden. ich recherchiere weiter, Danke, PWMBastler
Stefan U. schrieb: > Warum hast du das nicht gleicht im Eröffnungs-Thread geschrieben? Darüber bin ich ja auch gestolpert - Der Mega32 hat gar keinen Timer 3, deswegen die Nachfrage, welcher MC es denn nun wirklich ist.
:
Bearbeitet durch User
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.