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!

2 REPLIES 2

Your system clock is most likely not 400MHz, but 333.200MHz, most likely as consequence of a different primary clock source frequency than you've set (e.g. you assume 12MHz primary clock but it's in fact 10MHz).

HAL_RCC_GetHCLKFreq() etc. functions don't actually *measure* the HCLK/APB etc. frequencies; rather, they rely on a system variable (SystemCoreClock) being set properly in HAL_RCC_ClockConfig() by calling HAL_RCC_GetSysClockFreq(), which in turn uses one of HSI_VALUE/CSI_VALUE/HSE_VALUE set in stm32h7xx_hal_conf.h depeding on what primary clock source you've set.

JW

Saket_Om
ST Employee

Hello @sktech 

 

Did you measure the clock frequency? If the measured value is different from the theoretical value, it could be the reason for this issue.

To measure the clock frequency, you can use an oscilloscope to monitor the output on the MCO pin.

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar