2025-08-20 11:00 PM
Hi All,
I am writing a code to generate an PWM at output. I want to drive an H-bridge outside.All initializations I have done.
I am using TIM1 (advanced timer) for this purpose. I am using STM32F Discovery Board (Microcontroller is STM32F407) and STM32CubeIDE 1.19.0
The issue I am facing is whenever I get an interrupt i tried to load value from the LUT but its not working and generate unexpected PWM at output but when I load any fix value then PWM is generated at the output.
I am wondering why it is not generating the PWM from LUT.
below is my code. kindly tell me what I am doing wrong
volatile uint16_t sineIndex = 0;
#define SINE_TABLE_SIZE 10
uint16_t sineTable[SINE_TABLE_SIZE] = {400, 657, 794, 746, 537, 263, 54, 6, 143, 400};
int main(){
HAL_Init();
System_Clock_Source();
UART2_Init();
MX_GPIO_Init();
MX_TIM1_Init(); // Here all the settings are done related to PWM timings
MX_TIM2_Init();
SPWM_Start();
}
void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Enable GPIO clocks
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
// Configure TIM1 PWM outputs (PA8=CH1, PA9=CH1N, PB0=CH2N, PB1=CH2)
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
// For Debugging purpose
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// For Debugging purpose
GPIO_InitStruct.Pin = GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
void MX_TIM1_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 9;
htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
htim1.Init.Period = 800 - 1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_PWM_Init(&htim1);
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = sineTable[0];
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 10;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
}
void MX_TIM2_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 80; // 50Hz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_Base_Init(&htim2);
}
void SPWM_Start(void) {
// Start PWM generation
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
// Start synchronization timer (50Hz)
HAL_TIM_Base_Start_IT(&htim2);
// Start SPWM update timer (10kHz)
HAL_TIM_Base_Start_IT(&htim1);
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM1){
// 1. Enable the Clock for TIMER1
__HAL_RCC_TIM1_CLK_ENABLE();
// 3. Enable the IRQ and set the Priority (NVIC Settings)
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
}
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base){
if(htim_base->Instance == TIM2){
// Enable clock for TIMER2
__HAL_RCC_TIM2_CLK_ENABLE();
// Enable TIM2 interrupts
HAL_NVIC_EnableIRQ(TIM2_IRQn);
HAL_NVIC_SetPriority(TIM2_IRQn, 10, 0);
}
}
void TIM1_UP_TIM10_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim1);
}
// 50Hz interrupt handler
void TIM2_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim2);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM1) {
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, sineTable[0]);
// sineIndex = (sineIndex + 1) % SINE_TABLE_SIZE;
}
else if (htim->Instance == TIM2) {
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
}
}
now in the HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) when i do like sineTable[0], then value at 0 location is updated and generate 50% duty cycle continuously as expected but when i do like sineTable[sineIndex] and uncomment sineIndex = (sineIndex + 1) % SINE_TABLE_SIZE then the problem arises.
Kindly guide me what I am missing
2025-08-21 1:35 AM
Hello @AHayee
Please add a debug print or toggle to check the value of sineIndex and the value being written.
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
uint16_t value = sineTable[sineIndex];
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, value);
sineIndex = (sineIndex + 1) % SINE_TABLE_SIZE;