Skip to main content
YaoYaoLin
Associate
January 5, 2021
Question

About the stability of PWM mode

  • January 5, 2021
  • 1 reply
  • 779 views
void init_servo_timer()
{
 u16 tmp_period = 0;
 u16 CCR1_Val = 0;
 
 pulse_num_1ms = 0;
 pulse_period = (1/((float)pulse_num_1ms));
 tmp_period = (u16)(pulse_period * 36000);
 CCR1_Val = (tmp_period / 2 );
 
 TIM_DeInit(TIM1);
 /* (TIM_Period = TIM1->ARR) = 72MHz / prescaler */
 TIM_TimeBaseStructure.TIM_Period = (tmp_period); 
 TIM_TimeBaseStructure.TIM_Prescaler = (2 - 1); /* prescaler = 2 */
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x00;
 TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
 TIM_ITConfig(TIM1,TIM_IT_CC1,ENABLE);
 TIM_Cmd(TIM1, ENABLE);
 
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
 
 TIM_OCInitStructure.TIM_Pulse = CCR1_Val; /* TIM1-> CCR1 */
 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
 TIM_OC1Init(TIM1, &TIM_OCInitStructure);
 TIM_CtrlPWMOutputs(TIM1, ENABLE);
 
}
 
void TIM1_CC_IRQHandler(void)
{ 
 TEST_LED = ~TEST_LED;
 if ( TIM_GetITStatus(TIM1 , TIM_IT_CC1)) 
 {
 TIM_ClearITPendingBit(TIM1 , TIM_IT_CC1);
 
 pulse_cnt ++;
 if(am.dir)
 am.now_addr --; 
 else
 am.now_addr ++;
 
 if(pulse_cnt >= am.speed_cnt)
 {
 pulse_cnt = 0;
 if(am.now_addr == am.set_addr)
 {
 am.run = 0;
 am.speed_cnt = 0;
 }
 }
 }
 TEST_LED = ~TEST_LED;
 
}
// I put output_servo_am_pulse() function in 1ms loop 
void output_servo_am_pulse(void)
{ 
 if((am.h_run | am.run))
 {
 if(am.speed_cnt)
 {
 pulse_cnt = 0;
 TIM1->CNT = 1;
 TIM1->ARR = (u16)((36000 / am.speed_cnt));
 TIM1->CCR1 = (TIM1->ARR >> 1 );
 }
 }
 else
 {
 TIM1->ARR = 0;
 TIM1->CCR1 = 0;
 }
 
}

I was confusing why the pulse sometimes ARR should be reload (pulse 5.5us)but it didn't, but from the picture of waveform , I can still see the compare interrupt(TEST_LED 2us) still work.

By the way, I am using stm32f103xxx.

0693W000006HUcXQAW.png 

Can anyone help me for this problem? Thanks a lot.

This topic has been closed for replies.

1 reply

waclawek.jan
Super User
January 5, 2021

Is your logic analyzer fast enough to display a pulse 1 cycle long? And is the PWM output pin set fast enough in GPIO_CRx.MODEx to output a pulse 1 cycle long?

Btw. if you use only 50% duty cycle, it's more elegant to use Toggle mode of the timer.

JW

YaoYaoLin
YaoYaoLinAuthor
Associate
January 5, 2021

As you see the top of my logic analyzer its sample rate is 2MHz, that means it shows every 1/2MHz( = 500ns).

Do you mean this configuration?

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

Yeah, I know about Toggle mode. The important thing is I want the interrupt appears at negative edge trigger of the pulse. So that's why I pick PWM1 mode.

By the way, PWM mode is more alternative I thought.

The new things I found was, if I show TIM1(pulse generate) and TIM5(1ms loop) separately, then everything happened accurately. But when I put them together, then TIM1 and TIM5 affect each other, for instance, 1ms later become 1.001ms ~ 1.004ms, that would increase about 1~4us, 2us is large enough to make the interrupt of TIM1 delay.

Thanks for reply, WYL