cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G070 can't output PWM from Timer 1

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);

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Lead III

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.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

View solution in original post

14 REPLIES 14

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

0693W00000SuPR1QAN.jpg

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.

0693W00000SuPRfQAN.jpg

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​

gbm
Lead III

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.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Nice catch, gbm!

Indeed. Instead, CC3NP is set, in the "forbidden" combination with CC3P being zero [EDIT] not forbidden for Output [/EDIT]

JW

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);

Read out and check/post content of TIM and relevant GPIO registers.

JW

0693W00000SudsQQAR.jpg0693W00000SudsLQAR.jpg0693W00000SudsGQAR.jpg