Skip to main content
MaedeMpr
Associate
May 9, 2020
Solved

How to Change PWM Polarity without DeInit Timer??

  • May 9, 2020
  • 14 replies
  • 3145 views

I have read STM32f1 Reference Manual and tested STM32CubeMx functions but have not found any solution.

Is there a way to change PWM polarity without Deinitializing Timer??

This topic has been closed for replies.
Best answer by RMcCa

If the phase of the pwm signal is unimportant, write max - val instead of val to the ccr to invert the polarity.​

14 replies

berendi
Principal
May 9, 2020

I can't test it right now, but I think that toggling the CC*P bit in the CCER register can achieve this. E.g. to invert the polarity of timer 2 channel 3, do

TIM2->CCER ^= TIM_CCER_CC3P;

As it is a read-modify-write sequence, be careful that no other thread or interrupt handler accesses the register at the same time.

To avoid glitches in the output, you might want to reconfigure the pin to GPIO output e.g. on the compare event, invert the polarity, and switch back to alternate mode on the update event.

MaedeMpr
MaedeMprAuthor
Associate
May 9, 2020

No, It doesn't work I have tried it before, using CMSIS & Registers.Thanks for your reply, I've tested it again, but the result is the same.

I want to change my PWM signal as pictures:

0693W000000X9GiQAK.bmp0693W000000X9GxQAK.bmp

waclawek.jan
Super User
May 9, 2020

What have you tried exactly?

What is on those waveforms you posted? Which pin and how exactly did you generate those waveforms?

Read out content of the TIM registers before the change and after and compare/post together with respective waveforms.

JW

MaedeMpr
MaedeMprAuthor
Associate
May 10, 2020

I have configured my TIM8 & Channel1 as below to generate PWM :

void PWM_Init (void)
{
	TIM_TimeBaseInitTypeDef base;
	TIM_OCInitTypeDef ocx;
	NVIC_InitTypeDef nvic;
	
	//Enable Pin Configurations (Clock & GPIO)
	PioEnableClock( MAN_EN_PORT ); 
	PioSetOutput(MAN_EN_PORT,MAN_EN_PIN_N);
	PioSetPin(MAN_EN_PORT,MAN_EN_PIN_N);	
 
	//Timer & Channels Configurations (Clock & Alternative Functions)
	RccSetTimerClock( MAN_PWM_TIMER, ENABLE );
	PioEnableClock( MAN_PWM_1_PORT ); 
	
	PioSetAlternateFunS( MAN_PWM_1_PORT, MAN_PWM_1_PIN, PIO_PIN_AF_PP );
//	PioSetAlternateFunS( MAN_PWM_2_PORT, MAN_PWM_2_PIN, PIO_PIN_AF_PP );
	PioSetOutput(MAN_PWM_2_PORT,MAN_PWM_2_PIN_N);
	PioSetPin(MAN_PWM_2_PORT,MAN_PWM_2_PIN_N);
 
	//Timer Configurations 2KHz
	base.TIM_Prescaler = 18-1;
	base.TIM_Period = 2000;
	
	base.TIM_ClockDivision = 0;
	base.TIM_RepetitionCounter = 0;
	base.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit( MAN_PWM_TIMER, &base );
		
	//Channels Configurations as PWM
	ocx.TIM_OCMode = TIM_OCMode_PWM1;
	ocx.TIM_OutputState = ENABLE;
	ocx.TIM_OCPolarity = TIM_OCPolarity_Low;
	ocx.TIM_OCIdleState = TIM_OCIdleState_Reset;
	ocx.TIM_Pulse = 200;
	TIM_OC1Init( MAN_PWM_TIMER, &ocx );
 
//	ocx.TIM_OCMode = TIM_OCMode_PWM1;
//	ocx.TIM_OutputState = ENABLE;
//	ocx.TIM_OCPolarity = TIM_OCPolarity_High;
//	ocx.TIM_OCIdleState = TIM_OCPolarity_Low;
//	ocx.TIM_Pulse = 0;
//	TIM_OC2Init( MAN_PWM_TIMER, &ocx );
		
	//NVIC Configurations	
	nvic.NVIC_IRQChannel = TIM8_CC_IRQChannel;
	nvic.NVIC_IRQChannelCmd = ENABLE;
	nvic.NVIC_IRQChannelPreemptionPriority = 4;
	nvic.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init( &nvic );
	
	//! Enable Output
	TIM_CtrlPWMOutputs( MAN_PWM_TIMER, ENABLE );
	
	TIM_ARRPreloadConfig( MAN_PWM_TIMER, DISABLE );
	
	TIM_CCPreloadControl( MAN_PWM_TIMER, ENABLE );
	
	TIM_Cmd( MAN_PWM_TIMER, ENABLE );
	
}
 

I want to change my signal as pictures with a command, I have used both thses code to change polarity, CC1P in CCER changes but signal doesn't change:

TIM_OC1PolarityConfig(MAN_PWM_TIMER,TIM_OCPolarity_High);
MAN_PWM_TIMER->CCER ^= TIM_CCER_CC1P;

I have defined another function called PWM_change & DeInit Timer and change Output Compare Configuration as below, other configuration is the same as PWM_Init():

ocx.TIM_OCMode = TIM_OCMode_PWM1;
ocx.TIM_OutputState = ENABLE;
ocx.TIM_OCPolarity = TIM_OCPolarity_High;
ocx.TIM_OCIdleState = TIM_OCIdleState_Reset;
ocx.TIM_Pulse = 200;
TIM_OC1Init( MAN_PWM_TIMER, &ocx );

and it works calling PWM_Change() instead of changing Polarity. Bad story is it doesn't work when I remove DeInit function from first part of PWM_Change() function.

And I need use PWM signal in a PID controller and can not Init & DeInit Timer everytime.

I look for a better way to change PWM signal.

waclawek.jan
Super User
May 10, 2020

Which pin? Isn't it TIM8_CH1N?

Read out content of the TIM registers before the change and after and compare/post together with respective waveforms.

MaedeMpr
MaedeMprAuthor
Associate
May 10, 2020

PC.6 TIM8_CH1 default pin

waclawek.jan
Super User
May 10, 2020

Read out content of the TIM registers before the change and after and compare/post together with respective waveforms.

MaedeMpr
MaedeMprAuthor
Associate
May 10, 2020

0693W000000X9bgQAC.jpg0693W000000X9blQAC.jpg

CC1P in CCER has changed that is normal but OIS2 in CR2 has changed too.

waclawek.jan
Super User
May 10, 2020

OK so now if you perform the same change by directly writing to registers, you will see the waveform changing in the same way too.

To try it, you don't need to write any code, simply change it directly in the debugger.

JW

MaedeMpr
MaedeMprAuthor
Associate
May 11, 2020

I've tried but doesn't work as this. Thanks.

RMcCa
RMcCaBest answer
Senior II
May 10, 2020

If the phase of the pwm signal is unimportant, write max - val instead of val to the ccr to invert the polarity.​

MaedeMpr
MaedeMprAuthor
Associate
May 11, 2020

I tried this and it looks good. Thanks. It's solved my problem.