cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 PWM Output Incorrect Frequency (PE9, TIM1) despite Correct Configuration

sktech
Associate II

Problem:

I'm working with an STM32H743 and trying to generate a PWM signal (Center Aligned) on PE9 using Timer1 (TIM1). Although the PWM output is functioning, the frequency is not what I expect. I’m trying to generate a 1 kHz signal, but instead, I’m getting around 833 Hz, and I’ve confirmed that the period is incorrect.This is for driving a stepper motor.

What I have done so far:

  • Clock Configuration: The system clocks (HCLK, PCLK2, SYSCLK) are verified and appear to be configured correctly.
  • Timer Configuration: I'm using Timer1 in PWM Mode 1 with a prescaler of 199 and ARR of 999 to generate a 1 kHz PWM signal (expected 1 MHz timer clock). However, I’m getting an incorrect frequency (around 833 Hz).
  • GPIO Configuration: I’ve configured PE9 for TIM1 CH1 (PWM output).

     - My Code

#include <Arduino.h>

HardwareSerial SerialDebug(PA3, PA2);

const uint8_t PIN_STEP = PE9;
const uint8_t PIN_DIR = PE10;
const uint8_t PIN_ENA = PE7;

void setupTimer1()
{
    // Enable clocks
    __HAL_RCC_TIM1_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();

    // Get actual timer clock frequency
    uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
    uint32_t pclk1 = HAL_RCC_GetPCLK1Freq();
    uint32_t timclk = HAL_RCC_GetHCLKFreq();
    uint32_t sysclk = HAL_RCC_GetSysClockFreq();

    SerialDebug.printf("\nClock Configuration:\n");
    SerialDebug.printf("PCLK2: %lu Hz\n", pclk2);
    SerialDebug.printf("PCLK1: %lu Hz\n", pclk1);
    SerialDebug.printf("HCLK: %lu Hz\n", timclk);
    SerialDebug.printf("SYSCLK: %lu Hz\n", sysclk);
    SerialDebug.printf("SystemCoreClock: %lu Hz\n", SystemCoreClock);

    // Configure PE9 for Timer1 CH1 (PWM output)
    GPIO_InitTypeDef GPIO_Config = {0};
    GPIO_Config.Pin = GPIO_PIN_9;
    GPIO_Config.Mode = GPIO_MODE_AF_PP;
    GPIO_Config.Pull = GPIO_NOPULL;
    GPIO_Config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_Config.Alternate = GPIO_AF1_TIM1;
    HAL_GPIO_Init(GPIOE, &GPIO_Config);

    // Reset timer
    TIM1->CR1 = 0;
    TIM1->CR2 = 0;
    TIM1->SMCR = 0;
    TIM1->DIER = 0;
    TIM1->CCMR1 = 0;
    TIM1->CCER = 0;
    TIM1->BDTR = 0;

    // Timer configuration for HCLK = 200 MHz
    TIM1->PSC = 199;  // Divide by 200 (200 MHz / 200 = 1 MHz)
    TIM1->ARR = 999;  // ARR = 999 for 1 kHz (1000 cycles)
    TIM1->CCR1 = 500; // 50% duty cycle (ARR / 2)

    // Configure PWM mode 1 (OC1, PWM mode 1)
    TIM1->CCMR1 = (0b110 << 4) | TIM_CCMR1_OC1PE;
    TIM1->CCER = TIM_CCER_CC1E;  // Enable capture/compare channel 1
    TIM1->BDTR = TIM_BDTR_MOE;   // Main output enable
    TIM1->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN; // Enable auto-reload preload and the timer

    // For debug - read back the actual values
    SerialDebug.printf("\nTimer Configuration:\n");
    SerialDebug.printf("PSC: %lu\n", TIM1->PSC);
    SerialDebug.printf("ARR: %lu\n", TIM1->ARR);
    SerialDebug.printf("CCR1: %lu\n", TIM1->CCR1);
    SerialDebug.printf("CR1: 0x%08lX\n", TIM1->CR1);
    SerialDebug.printf("CCMR1: 0x%08lX\n", TIM1->CCMR1);

    // Start timer
    TIM1->CR1 |= TIM_CR1_CEN;
}

void setup()
{
    SerialDebug.begin(115200);
    delay(100);
    SerialDebug.println("\nClock Verification Test");

    // Configure control pins
    pinMode(PIN_DIR, OUTPUT);
    pinMode(PIN_ENA, OUTPUT);
    digitalWrite(PIN_ENA, HIGH); // Disabled
    digitalWrite(PIN_DIR, LOW);  // Forward

    setupTimer1();
}

void loop()
{
    if (SerialDebug.available())
    {
        char cmd = SerialDebug.read();
        if (cmd == 'e')
        {
            SerialDebug.println("Enabling motor");
            digitalWrite(PIN_ENA, LOW);
        }
        else if (cmd == 'd')
        {
            SerialDebug.println("Disabling motor");
            digitalWrite(PIN_ENA, HIGH);
        }
    }
}

 

 

  • Serial Output:

 

Clock Verification Test
Clock Configuration:
PCLK2: 100000000 Hz
PCLK1: 100000000 Hz
HCLK: 200000000 Hz
SYSCLK: 400000000 Hz
SystemCoreClock: 400000000 Hz

Timer Configuration:
PSC: 199
ARR: 999
CCR1: 500
CR1: 0x00000080
CCMR1: 0x00000068

 

  • What Happens:

    • Expected Output: A 1 kHz PWM signal with a 50% duty cycle on PE9.
    • Actual Output: The signal has an incorrect frequency of around 833 Hz (not 1 kHz as expected).

    Questions:

    1. Why am I seeing an incorrect frequency (833 Hz) instead of the expected 1 kHz?
    2. Is the timer configuration correct? I’ve ensured the prescaler and auto-reload values should generate a 1 kHz signal, but the output does not match.
    3. Could the issue be related to clock sources or the prescaler configuration? Should I double-check the timer clock frequency?

    What I’ve Tried:

    • Verified clock settings and timer registers.
    • Confirmed GPIO configuration for PE9 as an alternate function for TIM1 CH1.
    • Checked the serial output, and the values seem correct but the output does not match the expected signal frequency.

      Development Environment:

      • Platform: VS Code with PlatformIO
      • Framework: STM32 Arduino

    Any help or insight would be much appreciated. Thanks in advance!

0 REPLIES 0