STM32 PWM Output Incorrect Frequency (PE9, TIM1) despite Correct Configuration
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:
- Why am I seeing an incorrect frequency (833 Hz) instead of the expected 1 kHz?
- 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.
- 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!
