Uso STM32F103C8T6 para conducir la tira de LED RGB WS2812. Así que trato de configurar TIM1 para generar PWM usando DMA. Todo funciona bien, excepto el hecho de que recibo más olas de las que solicité. Casi todo el código que obtengo de STM32CubeMX está listo, aquí hay un código que utilizo:
Inicialización de tiempo:
static void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 3-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 30-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 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;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim1);
}
Inicialización DMA:
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
}
Utilizo la interrupción DMA para detener el temporizador:
void DMA1_Channel2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_tim1_ch1);
HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1);
}
Y main ():
TIM_HandleTypeDef htim1;
DMA_HandleTypeDef hdma_tim1_ch1;
int main(void)
{
HAL_Init();
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM1_Init();
uint8_t pData[] = {5,10,15,20,25};
HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1, (uint32_t *)pData,5);
while (1)
{
}
}
La CPU funciona en 72MHz, en la configuración del reloj. El reloj del temporizador APB1 está configurado para funcionar en 72MHz también.
Configuré el preescalador del temporizador a 3 y el contador a 30 pasos para generar ondas de 800 kHz. Envío a DMA 5 bytes y espero obtener 5 ondas con el aumento de pulso. Esto es lo que obtengo de hecho:
En lugar de 5 obtengo 7 oleadas por alguna razón. Los 2 últimos solo repitieron la 5ª ola.
¿Qué me perdí y cómo soluciono la situación?