2022-09-02 06:45 AM
We are having problems getting a PWM output from Timer 1(nothing on the PC10 pin.)
STM32G070
Low Level drivers
Alternate function 2 of PC10 is Timer1 channel 3
Code is based on STM32CubeG0-master\Projects\NUCLEO-G070RB\Examples_LL\TIM\TIM_PWMOutput_Init
The example in the LL drivers uses timer 6 where we need to use timer 1. Timer 1 has more features so we are guessing that there is another initialization that needs to be done. Here is the code but some of the comments still refer to timer 3. Clock setup first, then Timer 1 init and finally code before the main loop begins. The LL_TIM_EnableAllOutputs() call before the main loop was added from a HAL project that used timer 1.
Any suggestions would be appreciated.
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* - Set the pre-scaler value to have TIM1 counter clock equal to 10 kHz */
/* - Set the auto-reload value to have a counter frequency of 100 Hz */
/* TIM1CLK = SystemCoreClock / (APB prescaler & multiplier) */
TimOutClock = SystemCoreClock/1;
timxPrescaler = __LL_TIM_CALC_PSC(SystemCoreClock, 10000);
timxPeriod = __LL_TIM_CALC_ARR(TimOutClock, timxPrescaler, 100);
/* USER CODE END TIM1_Init 0 */
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
//LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0);
NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
TIM_InitStruct.Prescaler = timxPrescaler;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = timxPeriod;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM1, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM1);
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH3);
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.CompareValue = ((timxPeriod + 1 ) / 2);
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH3);
LL_TIM_SetTriggerOutput(TIM1, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM1);
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
// Clocking for Group C pins is already enabled
//LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC);
/**TIM1 GPIO Configuration
PC10 ------> TIM1_CH3
*/
GPIO_InitStruct.Pin = PWM_S_PC10;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_DOWN;
GPIO_InitStruct.Alternate = LL_GPIO_AF_2;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/* Clear the update flag */
LL_TIM_ClearFlag_UPDATE(TIM1);
/* Enable the update interrupt */
LL_TIM_EnableIT_UPDATE(TIM1);
/* Enable TIM1 outputs */
LL_TIM_EnableAllOutputs(TIM1);
/* Enable counter */
LL_TIM_EnableCounter(TIM1);
Solved! Go to Solution.
2022-09-02 11:40 PM
CCER content is incorrect - CC3E bit is not set, so CH3 PWM output is disabled.
You don't need to set the interrupt priority to 0 - it's the default after reset.
2022-09-02 11:35 AM
Read out and check/post content of TIM and relevant GPIO registers.
> Timer 1 has more features so we are guessing that there is another initialization that needs to be done.
Timer1 needs BDTR.MOE bit to be set, but although I don't understand the Cube/LL gobbledygook, it appears that the EnableAllOutput() function might've set that. We'll see that anyway when you post the registers content.
JW
2022-09-02 11:40 AM
2022-09-02 11:47 AM
Looks like that bit is set. We are only using the Low Level drivers because the G0 is in there and we don't use any of the Cube specific code generation.
2022-09-02 05:07 PM
This looks OK. Now check the GPIOC registers.
What hardware is this? You can check is PC10 if properly connected by setting it as GPIO output and toggling in software.
Btw. isn't PC10 one of those USB Power Delivery pins?
JW
2022-09-02 11:40 PM
CCER content is incorrect - CC3E bit is not set, so CH3 PWM output is disabled.
You don't need to set the interrupt priority to 0 - it's the default after reset.
2022-09-03 01:42 AM
Nice catch, gbm!
Indeed. Instead, CC3NP is set, in the "forbidden" combination with CC3P being zero [EDIT] not forbidden for Output [/EDIT]
JW
2022-09-06 06:21 AM
Modified the TIM_OC_InitStruct to the code below and the PWM is now present. So the LL_TIM_EnableAllOutputs(TIM1) call just before the main loop enables a different output? What is the proper way for starting/stopping the PWM once the control is running?
The comments in the definition of the LL_TIM_OC_InitTypeDef structure state that the uint32_t OCState can be modified later by "This feature can be modified afterwards using unitary functions @ref LL_TIM_CC_EnableChannel() or @ref L_TIM_CC_DisableChannel()"
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE;
TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.CompareValue = ((timxPeriod + 1 ) / 2);
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
TIM_OC_InitStruct.OCNPolarity = LL_TIM_OCPOLARITY_LOW;
TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
2022-09-06 11:42 AM
Read out and check/post content of TIM and relevant GPIO registers.
JW
2022-09-06 01:16 PM