Forum: Mikrocontroller und Digitale Elektronik STM32F4: PWM Duty und Periode einlesen


von Servotester (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte die Pulsweite und Periode eines typischen 50Hz RC-Servo 
Signals über einen Pin einlesen.
Theoretische Auflösung soll 1us betragen.

Dazu lasse den TIM4 (16Bit) mit einer Frequenz von 1MHz laufen und 
verwende die Anleitung aus dem RM0090, siehe Screenshot01.png

Code:
(Die 7 Stichpunkte aus der Anleitung im Screenshot habe ich mit 
Kommentaren 1..7 markiert)

    /* 1. */
    regval = TIM4->CCMR1;
    regval &= ~TIM_CCMR1_CC1S_1;
    regval |= TIM_CCMR1_CC1S_0;
    TIM4->CCMR1 = regval;

    /* 2. */
    regval = TIM4->CCER;
    regval &= ~TIM_CCER_CC1P;
    regval &= ~TIM_CCER_CC1NP;
    TIM4->CCER = regval;

    /* 3. */
    regval = TIM4->CCMR1;
    regval |= TIM_CCMR1_CC2S_1;
    regval &= ~TIM_CCMR1_CC2S_0;
    TIM4->CCMR1 = regval;

    /* 4. */
    regval = TIM4->CCER;
    regval |= TIM_CCER_CC2P;
    regval &= ~TIM_CCER_CC2NP;
    TIM4->CCER = regval;

    /* 5. */
    regval = TIM4->SMCR;
    regval |= TIM_SMCR_TS_2;
    regval &= ~TIM_SMCR_TS_1;
    regval |= TIM_SMCR_TS_0;
    TIM4->SMCR = regval;

    /* 6. */
    regval = TIM4->SMCR;
    regval |= TIM_SMCR_SMS_2;
    regval &= ~TIM_SMCR_SMS_1;
    regval &= ~TIM_SMCR_SMS_0;
    TIM4->SMCR = regval;

    /* 7. */
    regval = TIM4->CCER;
    regval |= TIM_CCER_CC1E;
    regval |= TIM_CCER_CC2E;
    TIM4->CCER = regval;

Periodenmessung:
Fallende Flanke: Timer Reset, erreichten Counter-Wert in das CCR1 
Register schreiben.

Pulsweitenmessung:
Steigende Flanke: aktueller Timer Counter-Wert in das CCR2 Register 
schreiben.

Die Register CCR1 und CCR2 werden asynchron in der main-Schleife 
ausgelesen.

Ergebnis: Pulsweitenmessung (CCR2) enthält den erwarteten Wert, je nach 
RC-Servo Signal zwischen 1000 und 2000.

Problem: Periodenmessung (CCR1) enthält mal die Pulsweite (1000 .. 2000) 
mal die Periodendauer (~20000).

Woran könnte es liegen, dass die Periode falsch gemessen wird?
Nach meinem Verständnis sollte das CCR1 Register nur
bei fallender Flanke aktualisiert werden und somit die Zeit 
(Counter-Wert) zwischen den fallenden Flanken enthalten.

von m.n. (Gast)


Lesenswert?

Servotester schrieb:
> ich möchte die Pulsweite und Periode eines typischen 50Hz RC-Servo
> Signals über einen Pin einlesen.

Es gibt einen Modus, bei dem bei einer Flanke des Eingangssignal der 
Zählerwert gespeichert und bei der anderen der Zählerstand gespeichert 
und gelöscht wird. Letzterer Wert ist die Periodendauer, aus dem 
Zwischenwert ergibt sich das Tastverhältnis.
Bei einem 16 Bit Timer mit 1 µs Auflösung funktioniert das ab 16 Hz 
Eingangsfrequenz.

Wenn Du es feiner und genauer haben willst: 
http://mino-elektronik.de/FM_407/fmeter_407.htm#a5

von m.n. (Gast)


Lesenswert?

m.n. schrieb:
> Es gibt einen Modus,

"PWM Input Mode" nennt sich das und ist im Ref-Manual unter TIM1 
beschrieben.

von Servotester (Gast)


Lesenswert?

Hallo,

genau diesen Modus möchte ich verwenden und habe es nach dem Reference 
Manual implementiert,

m.n. schrieb:
> und bei der anderen der Zählerstand gespeichert und gelöscht wird.
> Letzterer Wert ist die Periodendauer,

und dieser Teil funktioniert nicht wie erwartet.

von Servotester (Gast)


Lesenswert?

Hallo,

nur zur Info, falls jemand ebenfalls PWM mit einem STM32 einlesen will: 
Der Code oben ist korrekt und funktioniert.
Mein Problem war, dass ich weiter unten einen weiteren HAL-Lib Aufruf 
auf den betroffenen TIMER hatte, welcher nochmal das CCER Register 
überschrieben hatte.

Viele Grüße

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.