最近在做STM32正交编码测速,下载了一个看似官方提供的程序,却看不懂,希望看到贴的大侠不吝赐教。
s16 ENC_Get_Electrical_Angle(void)//s16 int16_t
{
s32 temp;
temp=(s32)(TIM_GetCounter(ENCODER_TIMER))*(s32)(UINT32_MAX/(4*ENCODER_PPR));//s32 int32_t
return((s16)(temp/65536)); // s16 result
}
/*******************************************************************************
* Function Name : ENC_Clear_Speed_Buffer
* Description : Clear speed buffer used for average speed calculation
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void ENC_Clear_Speed_Buffer(void)
{
u32 i;
for(i=0;i
{
hSpeed_Buffer=0;
}
bIs_First_Measurement = 1;
}
/*******************************************************************************
* Function Name : ENC_Calc_Rot_Speed
* Description : Compute return latest speed measurement
* Input : None
* Output : s16
* Return : Return the speed in 0.1 Hz resolution.
*******************************************************************************/
s16 ENC_Calc_Rot_Speed(void)//int16_t
{
s32 wDelta_angle;
u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
signed long long temp;
s16 haux;
if(!bIs_First_Measurement)
{
// 1st reading of overflow counter
hEnc_Timer_Overflow_sample_one=hEncoder_Timer_Overflow;
// 1st reading of encoder timer counter
hCurrent_angle_sample_one=ENCODER_TIMER->CNT;
// 2nd reading of overflow counter
hEnc_Timer_Overflow_sample_two=hEncoder_Timer_Overflow;
// 2nd reading of encoder timer counter
hCurrent_angle_sample_two=ENCODER_TIMER->CNT;
// Reset hEncoder_Timer_Overflow and read the counter value for the next
// measurement
hEncoder_Timer_Overflow=0;
haux=ENCODER_TIMER->CNT;
if(hEncoder_Timer_Overflow!=0)
{
haux = ENCODER_TIMER->CNT;
hEncoder_Timer_Overflow = 0;
}
if(hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
{
//Compare sample 1 & 2 and check if an overflow has been generated right
//after the reading of encoder timer. If yes, copy sample 2 result in
//sample 1 for next process
hCurrent_angle_sample_one = hCurrent_angle_sample_two;
hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
}
if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)
{
// encoder timer down-counting
wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle -
(hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
}
else
{
//encoder timer up-counting
wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle
(hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
}
// speed computation as delta angle * 1/(speed sempling time)
temp = (signed long long)(wDelta_angle*SPEED_SAMPLING_FREQ);
temp *= 10; // 0.1 Hz resolution
temp /= (4*ENCODER_PPR);
} //is first measurement, discard it
else
{
bIs_First_Measurement = 0;
temp = 0;
hEncoder_Timer_Overflow = 0;
haux = ENCODER_TIMER->CNT;
// Check if Encoder_Timer_Overflow is still zero. In case an overflow IT
// occured it resets overflow counter and wPWM_Counter_Angular_Velocity
if (hEncoder_Timer_Overflow != 0)
{
haux = ENCODER_TIMER->CNT;
hEncoder_Timer_Overflow = 0;
}
}
hPrevious_angle = haux;
return((s16) temp);
}
/*******************************************************************************
* Function Name : ENC_Calc_Average_Speed
* Description : Compute smoothed motor speed based on last SPEED_BUFER_SIZE
informations and store it variable
* Input : None
* Output : s16
* Return : Return rotor speed in 0.1 Hz resolution. This routine
will return the average mechanical speed of the motor.
*******************************************************************************/
void ENC_Calc_Average_Speed(void)
{
s32 wtemp;
u32 i;
wtemp = ENC_Calc_Rot_Speed();
/* Compute the average of the read speeds */
hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
bSpeed_Buffer_Index++;
if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)
{
bSpeed_Buffer_Index = 0;
}
wtemp=0;
for (i=0;i
{
wtemp += hSpeed_Buffer;
}
wtemp /= SPEED_BUFFER_SIZE;
hRot_Speed = ((s16)(wtemp));
}
/*******************************************************************************
* Function Name : TIM4_IRQHandler
* Description : This function handles TIMx Update interrupt request.
Encoder unit connected to TIM4
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM4_IRQHandler(void)
{
/* Clear the interrupt pending flag */
TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
if (hEncoder_Timer_Overflow != UINT16_MAX )
{
hEncoder_Timer_Overflow++;
}
}