2025-09-05 1:22 AM - last edited on 2025-09-05 5:26 AM by Saket_Om
I'm trying to drive the PWM of an STM32G0 but the waveform generated had an inconsistent period between bit 0 and bit 1, and I can't understand why
I'm using TIMER 4 on Channel 2. On the main.c I'm initializing MX_DMA_Init
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA1_Channel2_3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
}
and TIM4 configured as
void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
HAL_TIM_Base_DeInit(&htim4);
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 60 - 1;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
HAL_TIM_MspPostInit(&htim4);
}
The HAL_TIM_MspPostInit has
__HAL_RCC_GPIOD_CLK_ENABLE();
/**TIM4 GPIO Configuration
PD13 ------> TIM4_CH2
PD14 ------> TIM4_CH3
PD15 ------> TIM4_CH4
*/
GPIO_InitStruct.Pin = OUT_uC3_Pin|OUT_uC2_Pin|OUT_uC1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
with
#define OUT_uC3_Pin GPIO_PIN_13
#define OUT_uC3_GPIO_Port GPIOD
The led_render function correctly fills the buffer with
// Fill with alternating pattern: HI, LO, HI, LO...
for(uint8_t i = 0; i < WR_BUF_LEN; i++) {
wr_buf[i] = (i % 2) ? PWM_HI : PWM_LO;
}
HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_2, (uint32_t *) wr_buf, WR_BUF_LEN);
and in the .h
#define PWM_HI (38)
#define PWM_LO (19)
// LED parameters
#define NUM_BPP (3) // WS2812B
#define NUM_PIXELS (18)
#define NUM_BYTES (NUM_BPP * NUM_PIXELS)
But for some reason I'm seeing a the strange, not correct, waveform
Am I doing something wrong?
2025-09-05 3:59 AM - edited 2025-09-05 4:07 AM
What is the expected waveform and how is the observed one different?
[EDIT] Assuming timer clock is equal to system clock, 60 cycles may be sufficient for DMA, but AFAIK Cube/HAL does not use the Update event to load TIMx_CCRx but the CC event, which may leave much less time, and result in DMA not feeding the TIMx_CCRx fast enough. I don't say this *is* the problem here (as I don't know what are the symptoms, see my first question), but may be a thing to consider. Try longer times, or higher system clock frequency.
JW
2025-09-05 4:46 AM
What is the declaration of wr_buf and where is it placed?