cancel
Showing results for 
Search instead for 
Did you mean: 

How to Change PWM Polarity without DeInit Timer??

MaedeMpr
Associate II

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??

1 ACCEPTED SOLUTION

Accepted Solutions
RMcCa
Senior II

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

View solution in original post

16 REPLIES 16
berendi
Principal

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
Associate II

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

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
Associate II

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.

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
Associate II

PC.6 TIM8_CH1 default pin

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

MaedeMpr
Associate II

0693W000000X9bgQAC.jpg0693W000000X9blQAC.jpg

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

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