📄 stm32f10x_hall.c
字号:
* Returns : Rotor mechanical frequency, with 0.1Hz resolution.
* Comments : Result is zero if speed is too low (glitches at start for instance)
* Excessive speed (or high freq glitches will result in a pre-defined
* value returned.
* Warning : Maximum expectable accuracy depends on CKTIM: 72MHz will give the
* best results.
*******************************************************************************/
s16 HALL_GetSpeed ( void )
{
s32 wAux;
if( hRotorFreq_dpp == HALL_MAX_PSEUDO_SPEED) //条件是:
//(PeriodMeasAux.wPeriod < (u32)SPEED_OVERFLOW )
{
return (HALL_MAX_SPEED); //最高转速,
}
else
{
wAux = ((hRotorFreq_dpp* SAMPLING_FREQ * 10)/(65536*POLE_PAIR_NUM));
return (s16)wAux;
}
}
/*******************************************************************************
* ROUTINE Name : Hall_GetRotorFreq
*
* Description : This routine returns Rotor frequency with an unit that can be
* directly integrated to get the speed in the field oriented
* control loop.
*
* Input : None
* Output : None
* Returns : Rotor mechanical frequency with rad/PWM period unit
* (here 2*PI rad = 0xFFFF).
* Comments : Result is zero if speed is too low (glitches at start for instance)
* Excessive speed (or high freq glitches will result in a pre-defined
* value returned.
* Warning : Maximum expectable accuracy depends on CKTIM: 72MHz will give the
* best results.
*******************************************************************************/
s16 HALL_GetRotorFreq ( void )
{
PeriodMeas_s PeriodMeasAux;
if ( DoRollingAverage)
{
PeriodMeasAux = GetAvrgHallPeriod();
}
else
{ // Raw period
PeriodMeasAux = GetLastHallPeriod();
}
if (HallTimeOut == TRUE)
{
hRotorFreq_dpp = 0;
}
else
{
if(PeriodMeasAux.bDirection != ERROR)
//No errors have been detected during rotor speed information extrapolation
{
if ( HALL_TIMER->PSC >= HALL_MAX_RATIO )/* At start-up or very low freq */
{ /* Based on current prescaler value only */
hRotorFreq_dpp = 0; //马达启动或者转速非常低
}
else
{ //转速太低
if( PeriodMeasAux.wPeriod > MAX_PERIOD) /* Speed is too low */
{
hRotorFreq_dpp = 0;
}
else
{ /*Avoid u32 DIV Overflow*/
if ( PeriodMeasAux.wPeriod > (u32)SPEED_OVERFLOW )
{
if (HALL_GetCaptCounter()<2)// First capture must be discarded
{
hRotorFreq_dpp=0; //第一次的计数器捕捉丢弃
} //最高速 //最低速
else //PSEUDO_FREQ_CONV 介于 SPEED_OVERFLOW和 MAX_PERIOD之间。
{
hRotorFreq_dpp = (s16)((u16) (PSEUDO_FREQ_CONV /
PeriodMeasAux.wPeriod));
hRotorFreq_dpp *= PeriodMeasAux.bDirection;
}
}
else // <=96000 (PeriodMeasAux.wPeriod < (u32)SPEED_OVERFLOW )
{
hRotorFreq_dpp = HALL_MAX_PSEUDO_SPEED; //-32768 速度太高了
}
}
}
}
}
return (hRotorFreq_dpp);
}
/*******************************************************************************
* ROUTINE Name : HALL_ClrTimeOut
*
* Description : Clears the flag indicating that that informations are lost,
* or speed is decreasing sharply.
* Input : None
* Output : Clear HallTimeOut
* Return : None
*******************************************************************************/
void HALL_ClrTimeOut(void)
{
HallTimeOut = FALSE;
}
/*******************************************************************************
* ROUTINE Name : HALL_IsTimedOut
*
* Description : This routine indicates to the upper layer SW that Hall
* sensors information disappeared or timed out.
* Input : None
* Output : None
* Return : boolean, TRUE in case of Time Out
* Note : The time-out duration depends on timer pre-scaler,
* which is variable; the time-out will be higher at low speed.
*******************************************************************************/
bool HALL_IsTimedOut(void)
{
return(HallTimeOut);
}
/*******************************************************************************
* ROUTINE Name : Hall_GetCaptCounter
*
* Description : Gives the number of Hall sensors capture interrupts since last call
* of the HALL_ClrCaptCounter function.
* Input : None
* Output : None
* Return : u16 integer (Roll-over is prevented in the input capture
* routine itself).
*******************************************************************************/
u16 HALL_GetCaptCounter(void)
{
return(hCaptCounter);
}
/*******************************************************************************
* ROUTINE Name : HALL_ClrCaptCounter
*
* Description : Clears the variable holding the number of capture events.
* Input : None
* Output : hCaptCounter is cleared.
* Return : None
*******************************************************************************/
void HALL_ClrCaptCounter(void)
{
hCaptCounter = 0;
}
/*******************************************************************************
* ROUTINE Name : GetLastHallPeriod
*
* Description : returns the rotor pseudo-period based on last capture
* Input : None
* Output : None
* Return : rotor pseudo-period, as a number of CKTIM periods
*******************************************************************************/
PeriodMeas_s GetLastHallPeriod(void)
{
PeriodMeas_s PeriodMeasAux;
u8 bLastSpeedFIFO_Index;
// Store current index to prevent errors if Capture occurs during processing
bLastSpeedFIFO_Index = bSpeedFIFO_Index; //防止中断发生改变索引号
// This is done assuming interval between captures is higher than time
// to read the two values
PeriodMeasAux.wPeriod = SensorPeriod[bLastSpeedFIFO_Index].hCapture;
PeriodMeasAux.wPeriod *= (SensorPeriod[bLastSpeedFIFO_Index].hPrscReg + 1);
PeriodMeasAux.bDirection = SensorPeriod[bLastSpeedFIFO_Index].bDirection;
return (PeriodMeasAux);
}
/*******************************************************************************
* ROUTINE Name : GetAvrgHallPeriod
*
* Description : returns the rotor pseudo-period based on 4 last captures
* Input : None
* Output : None
* Return : averaged rotor pseudo-period, as a number of CKTIM periods
* Side effect: the very last period acquired may not be considered for the
* calculation if a capture occurs during averaging.
*******************************************************************************/
PeriodMeas_s GetAvrgHallPeriod(void)
{
u32 wFreqBuffer, wAvrgBuffer, wIndex;
PeriodMeas_s PeriodMeasAux;
wAvrgBuffer = 0;
for ( wIndex = 0; wIndex < HALL_SPEED_FIFO_SIZE; wIndex++ )
{
// Disable capture interrupts to have presc and capture of the same period
HALL_TIMER->DIER &= ~TIM_IT_CC1; // NB:Std libray not used for perf issues
wFreqBuffer = SensorPeriod[wIndex].hCapture;
wFreqBuffer *= (SensorPeriod[wIndex].hPrscReg + 1);
HALL_TIMER->DIER |= TIM_IT_CC1; // NB:Std libray not used for perf issue
wAvrgBuffer += wFreqBuffer; // Sum the whole periods FIFO
PeriodMeasAux.bDirection = SensorPeriod[wIndex].bDirection;
}
// Round to upper value
wAvrgBuffer = (u32)(wAvrgBuffer + (HALL_SPEED_FIFO_SIZE/2)-1);
wAvrgBuffer /= HALL_SPEED_FIFO_SIZE; // Average value
PeriodMeasAux.wPeriod = wAvrgBuffer;
return (PeriodMeasAux);
}
/*******************************************************************************
* ROUTINE Name : HALL_StartHallFiltering
*
* Description : Set the flags to initiate hall speed values smoothing mechanism.
* Input : None
* Output : The result of the next capture will be copied in the whole array
* to have 1st average = last value.
* Return : None
* Note: The initialization of the FIFO used to do the averaging will be done
* when the next input capture interrupt will occur.
*******************************************************************************/
void HALL_StartHallFiltering( void )
{
InitRollingAverage = TRUE;
}
/*******************************************************************************
* ROUTINE Name : HALL_ReadHallState
*
* Description : Read the GPIO Input used for Hall sensor IC and return the state
* Input : None
* Output : None
* Return : STATE_X
*
*******************************************************************************/
u8 ReadHallState(void)
{
u8 ReadValue;
#if defined(TIMER2_HANDLES_HALL)
ReadValue = (u8)(GPIO_ReadInputData(GPIOA)) & GPIO_MSK;
#elif defined(TIMER3_HANDLES_HALL)
ReadValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)<<2;
ReadValue |= GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)<<1;
ReadValue |= GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7);
#elif defined(TIMER4_HANDLES_HALL)
ReadValue = ((u8)(GPIO_ReadInputData(GPIOA))>>6) & GPIO_MSK;
#endif
return(ReadValue);
}
/*******************************************************************************
* ROUTINE Name : HALL_GetElectricalAngle
*
* Description : Export the variable containing the latest angle updated by IC
* interrupt
* Input : None
* Output : None
* Return : Electrical angle s16 format
*
*******************************************************************************/
s16 HALL_GetElectricalAngle(void)
{
return(hElectrical_Angle);
}
/*******************************************************************************
* ROUTINE Name : HALL_IncElectricalAngle
*
* Description : Increment the variable containing the rotor position information.
* This function is called at each FOC cycle for integrating
* the speed information
* Input : None
* Output : None
* Return : Electrical angle s16 format
*
*******************************************************************************/
void HALL_IncElectricalAngle(void)
{
static s16 hPrevRotorFreq;
if (hRotorFreq_dpp != HALL_MAX_PSEUDO_SPEED)
{
hElectrical_Angle += hRotorFreq_dpp;
hPrevRotorFreq = hRotorFreq_dpp;
}
else
{
hElectrical_Angle += hPrevRotorFreq;
}
}
/*******************************************************************************
* ROUTINE Name : HALL_Init_Electrical_Angle
*
* Description : Read the logic level of the three Hall sensor and individuates
* this way the position of the rotor (+/- 30
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -