Einstellen der Frequenz einer PWM auf einem STM32

Ich versuche, eine Funktion zu schreiben, die eine gewünschte PWM-Frequenz verwendet und den Timer basierend auf diesem Wert einstellt:

void initTimer(unsigned int freq ){

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    TIM_TimeBaseInitTypeDef timerInitStructure;
    timerInitStructure.TIM_Prescaler = 1000;
    timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    timerInitStructure.TIM_Period = 1000;
    timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    timerInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3, &timerInitStructure);
    TIM_Cmd(TIM3, ENABLE);

    TIM_OCInitTypeDef outputChannelInit;
    outputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
    outputChannelInit.TIM_Pulse = 500;
    outputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
    outputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
    // the first channel
    TIM_OC1Init(TIM3, &outputChannelInit);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);

}

Der Code funktioniert gut und generiert die erwartete PWM. Mein Problem ist, dass ich nicht weiß, wie ich den Wert des Vorteilers basierend auf der angegebenen Frequenz berechnen soll. Im obigen Beispiel sind die Werte fest.

Irgendeine Idee, wie ich das machen kann? Vielen Dank im Voraus!

Lesen Sie das Datenblatt/Programmierhandbuch für Ihren Chip. Insbesondere der Abschnitt über PWM. Es hat alles. Wenn Sie es nicht finden können, suchen Sie nach einigen Anwendungshinweisen (ja, ich weiß, STMs-Dokumente sind etwas schwierig zu navigieren ...).

Antworten (2)

Kurz gesagt, Sie möchten die Gleichung erfüllen:

Vorteiler * Überlauf = Periode-in-Zyklen = Taktzyklen pro Sekunde / Frequenz

Eine gute Möglichkeit, die Prescaler- und Overflow-Werte für PWM zu berechnen, besteht darin, den kleinstmöglichen Prescaler zu wählen und dann den Overflow auf die gewünschte Gesamtfrequenz zu trimmen. Dadurch bleibt der Overflow-Wert so groß wie möglich, was dann die größte Präzision ergibt, wenn Sie später das Tastverhältnis der Wellenform modulieren möchten.

period_cyclesWenn beispielsweise die Taktfrequenz 72 MHz beträgt und Sie eine 250-Hz-Ausgangsrechteckwelle (50 % Einschaltdauer) wünschen, beträgt die gesamte Ausgangswellenformperiode in Taktzyklen ( ) 72 MHz / 250 Hz = 288000 Zyklen. Der Wert des Timers overflowbeträgt normalerweise höchstens 16 Bit ( 0xFFFF, oder 65535), der Vorteiler muss so sein, dass prescaler * overflow >= period_cycles, und 288000.0 / 0xFFFF => 4.39459..., also sollte der Vorteiler sein 5. Schließlich , 288000 / 5 => 57600was eine schöne runde Zahl für die ist overflow(Sie würden dies auf die nächste Ganzzahl runden wollen, wenn dies nicht der Fall wäre).

Hier ist ein Code, der den obigen Algorithmus implementiert, einschließlich der entsprechenden Rundung mit C-Integer-Arithmetik:

#define CLOCK_CYCLES_PER_SECOND  72000000
#define MAX_RELOAD               0xFFFF

uint32_t period_cycles = CLOCK_CYCLES_PER_SECOND / freq;
uint16_t prescaler = (uint16)(period_cycles / MAX_RELOAD + 1);
uint16_t overflow = (uint16)((period_cycles + (prescaler / 2)) / prescaler);
uint16_t duty = (uint16)(overflow / 2);

freq == 0Natürlich sollten Sie in Ihrem eigentlichen Code nach Grenzfällen wie oder suchen freq > CLOCK_CYCLES_PER_SECOND/2.

Ich habe das immer so gemacht, aber es ist gut, das so schön geschrieben zu haben.
Wenn Sie keine 50 % Abgabe wünschen, kann sie wie folgt berechnet werden: Abgabe = Überlauf * Prozent_Pflicht / 100.

Um Eugenes Kommentar zu erweitern ... im Datenblatt handelt es sich in den relevanten Abschnitten um Uhren (es gibt ein schönes Diagramm, wie sie abgeleitet werden) und PWM. Und möglicherweise gibt es auch ein Dokument, das die Bibliothek beschreibt, die Sie verwenden (FWLib oder was ist das?).

Ihr Init-Code zeigt, dass die Timer- / PWM-Uhr von PCLK1 (APB1) abgeleitet ist, was normalerweise eine CPU-Uhr ist, die durch etwas geteilt wird. Es gibt Funktionen zum Abrufen von Uhren (RCC_xxx), damit Sie die Nummer abrufen können. Danach haben Sie im Grunde zwei Teiler, Prescaler und Period, also erhalten Sie PCLK1/1000000.