Cómo configurar STM32F4s TIM1 y 8 para PWM

Configuré el temporizador 4 para PWM con el siguiente código y conecté el LED al pin configurado. Está funcionando.

TIM_TimeBaseInitTypeDef TIM_BaseStruct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);    // Enable bus clock

TIM_BaseStruct.TIM_Prescaler = 0;   // Set prescaler (frequency divider)
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_CenterAligned1;    // Set counting mode (up, down, center-aligned) to center aligned for better motor control
TIM_BaseStruct.TIM_Period = 4000; // Set timer period (timer reset/change direction value)
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);    // Initialize timer with chosen settings
TIM_Cmd(TIM4, ENABLE);  // Start timer

GPIO_InitTypeDef GPIO_InitStruct;

/* Clock for GPIOD */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);

/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStruct);

TIM_OCInitTypeDef TIM_OCStruct;

TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = 1999;
TIM_OC1Init(TIM4, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);

pero cuando configuré TIM 1 y conecté el LED a su pin, no sucedió nada (probé el pin por separado cambiándolo como salida para asegurarme de que conecté el LED al pin correcto y se encendió)

TIM_TimeBaseInitTypeDef TIM_BaseStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);    // Enable bus clock

TIM_BaseStruct.TIM_Prescaler = 1;   // Set prescaler (frequency divider)
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_CenterAligned1;    // Set counting mode (up, down, center-aligned) to center aligned for better motor control
TIM_BaseStruct.TIM_Period = 4000; // Set timer period (timer reset/change direction value)
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_BaseStruct);    // Initialize timer with chosen settings
TIM_Cmd(TIM1, ENABLE);  // Start timer

GPIO_InitTypeDef GPIO_InitStruct;

/* Clock for GPIOE */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1);

/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOE, &GPIO_InitStruct);

TIM_OCInitTypeDef TIM_OCStruct;

TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = 1999;
TIM_OC1Init(TIM1, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

¿Hay algo diferente que deba hacer con los temporizadores avanzados para que funcionen con pwm? También tuve éxito con TIM3 y TIM12 (que son temporizadores de propósito general), pero no con TIM8 (que también es un temporizador avanzado).

Respuestas (2)

Con la ayuda de personas en el foro STM32, descubrí que me faltaba el siguiente código adicional para hacer que el temporizador avanzado funcione de la misma manera que el temporizador de propósito general:

TIM_BDTRInitTypeDef TIM_BDTRInitStruct;
TIM_BDTRStructInit(&TIM_BDTRInitStruct);
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStruct);
TIM_CCPreloadControl(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);

Nota: Los canales deben inicializarse antes de llamar al código para funciones avanzadas. Si intenta inicializar los canales después de eso, puede haber problemas (mi LED conectado al canal 3, que se inicializó después de las funciones avanzadas, siempre estaba ENCENDIDO y no respondía a los cambios de pwm, curiosamente el canal 4 funcionaba pero también se inicializó después de las funciones avanzadas ).

Esta es una pregunta antigua, pero tengo un comentario general sobre su código, ya que podría causar errores (me encontré con este error hoy, lo que me impide usar el PWM en absoluto). Lo estoy publicando como respuesta porque todavía no puedo usar comentarios con mi nueva cuenta.

Cuando se usan estructuras de inicio, es una buena práctica llamar a sus funciones de inicio de estructura correspondientes antes de hacer cualquier otra cosa, por ejemplo, aquí TIM_TimeBaseStructInit()for TIM_TimeBaseInitTypeDef, GPIO_StructInit()for GPIO_InitTypeDefy TIM_OCStructInit()for TIM_OCInitTypeDef.

Un miembro de estructura no inicializado puede desencadenar un comportamiento inesperado. En su código, no inicializó todos los miembros de TIM_OCStruct, lo que significa que TIM_OC1Init()utilizará valores sucios para iniciar los registros del temporizador. Debe llamar TIM_OCStructInit()o configurar a todos los miembros individualmente.