2021-01-04 06:19 PM
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.
Can anyone help me for this problem? Thanks a lot.
2021-01-05 01:16 AM
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
2021-01-05 03:17 AM
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