AVR-PWM-Ausgangsverzögerung vor dem Start

Ich verwende einen ATtiny85 , um eine PWM-Ausgabe zu erzeugen (unter Verwendung von Timer0 im OCR-Modus), und diese PWM-Ausgabe wird in regelmäßigen Abständen ein- und ausgeschaltet. Ich stelle fest, dass beim Einschalten des PWM-Ausgangs eine Verzögerung auftritt, bevor er tatsächlich mit der Ausgabe beginnt.

Schauen Sie sich den Screenshot unten an, die grüne Linie zeigt den Zustand, in den ich die PWM versetze (entweder ein- oder ausgeschaltet über TCCR1), und dennoch gibt es eine Verzögerung von etwas, das wie ein vollständiger Zyklus aussieht, bevor es beginnt. Ich habe auch versucht, TCNT0 auf 0 zurückzusetzen, aber das hatte keine Wirkung.

Geben Sie hier die Bildbeschreibung ein

(Die Zeitbasis beträgt 20 µs.)

SET(DDRB, PB1);
SET(DDRB, PB2);

// Set up PWM for 460 kHz with 8 MHz clock
TCCR1 = (1<<PWM1A) | (1<<COM1A1) | (1<<COM1A0) | (1<<CS10); // Prescaler = none;
GTCCR = (1<<FOC1A);
OCR1A = 9; // 460.750 kHz
OCR1C = 18;

#define BIT_DELAY ((1000000/38400))

while(1) {
    SET(TCCR1, PWM1A);
    SET(PORTB, PB2);
    _delay_us(BIT_DELAY);
    CLR(TCCR1, PWM1A);
    CLR(PORTB, PB2);
    _delay_us(BIT_DELAY);
}
Kannst du bitte das Code-Snippet teilen
ja hinzugefügt, danke! Ein Pin ist grün und der andere ist der Timer-Ausgang

Antworten (1)

Das Deaktivieren des PWM-Modus von TIMER1 stoppt nichtTCNT das Zählen – es stoppt nur die PWM-Ausgabe.

Wenn Sie also den Ausgang mit deaktivieren CLR(TCCR1, PWM1A), TCNT1zählt er fröhlich weiter und wird nicht zurückgesetzt, 0wenn er trifft OCR1C, da er sich nicht mehr im PWM-Modus befindet. Es läuft direkt vorbei OCR1Cund zählt weiter, 255bis es überrollt.

Die Verzögerung, die Sie sehen, ist die Zeit, die benötigt wird, TCNT1um von wo auch immer zu zählen OCR1C, wenn Sie den PWM-Modus wieder auf aktivieren. Zu diesem Zeitpunkt wird er zurückgesetzt 0und beginnt mit einem normalen PWM-Zyklus.

Eine Möglichkeit zu steuern, wann der PWM-Zyklus beginnt, nachdem Sie den PWM-Modus aktiviert haben, besteht darin, den Zähler vorab zu laden, sodass er keinen Umlauf ausführen muss, bevor die normalen PWM-Vergleichspunkte in und dann gestartet OCR1Awerden OCR1C. Zum Beispiel...

    while(1) {
        TCNT1=254;
        SET(TCCR1, PWM1A);
        SET(PORTB, PB2);
        _delay_us(BIT_DELAY);
        CLR(TCCR1, PWM1A);
        CLR(PORTB, PB2);
        _delay_us(BIT_DELAY);
    }

... erzeugt diese Wellenform ...

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass dieser Ansatz für mich wie ein Hack erscheint und dass es wahrscheinlich bessere Möglichkeiten gibt, das PWM-Signal zu steuern, die einfacher wären, aber die beste Wahl würde von Ihrer Anwendung abhängen.

Danke. Hätte nie bemerkt, dass der ocr1c-Vergleich auch deaktiviert wurde!