📄 stm32f10x_hall.c
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : stm32f10x_hall.c
* Author : IMS Systems Lab
* Date First Issued : 21/11/07
* Description : Module handling speed feedback provided by three Hall
* sensors
********************************************************************************
* History:
* 21/11/07 v1.0
* 29/05/08 v2.0
* 26/06/08 v2.0.1
* 27/06/08 v2.0.2
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* THIS SOURCE CODE IS PROTECTED BY A LICENSE.
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
* IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_hall.h"
#include "MC_hall_prm.h"
#include "MC_Globals.h"
#include "stm32f10x_MClib.h"
#include "stm32f10x_it.h"
/* Private define ------------------------------------------------------------*/
#define HALL_MAX_SPEED_FDBK (u16)(HALL_MAX_SPEED_FDBK_RPM/6 * POLE_PAIR_NUM) //2500
#define HALL_MIN_SPEED_FDBK (u16)(HALL_MIN_SPEED_FDBK_RPM/6* POLE_PAIR_NUM) //5
#define LOW_RES_THRESHOLD ((u16)0x5500u)// If capture below, ck prsc decreases
#define ROTOR_SPEED_FACTOR ((u32)((CKTIM*10)) / 3) // =240,000,000
#define PSEUDO_FREQ_CONV ((u32)(ROTOR_SPEED_FACTOR / (SAMPLING_FREQ * 10)) * 0x10000uL)
#define SPEED_OVERFLOW ((u32)(ROTOR_SPEED_FACTOR / HALL_MAX_SPEED_FDBK)) //96000
#define MAX_PERIOD ((u32)(ROTOR_SPEED_FACTOR / HALL_MIN_SPEED_FDBK)) //48000000
#define HALL_COUNTER_RESET ((u16) 0)
#define S16_PHASE_SHIFT (s16)(HALL_PHASE_SHIFT * 65536/360)
#define S16_120_PHASE_SHIFT (s16)(65536/3)
#define S16_60_PHASE_SHIFT (s16)(65536/6)
//=================HALL信号输入相位======================
//不使用反相器,如:74HC14,同相输入
#define STATE_0 (u8)0
#define STATE_1 (u8)1
#define STATE_2 (u8)2
#define STATE_3 (u8)3
#define STATE_4 (u8)4
#define STATE_5 (u8)5
#define STATE_6 (u8)6
#define STATE_7 (u8)7
//使用74HC14反相输入信号
/*
#define STATE_0 (u8)7
#define STATE_1 (u8)6
#define STATE_2 (u8)5
#define STATE_3 (u8)4
#define STATE_4 (u8)3
#define STATE_5 (u8)2
#define STATE_6 (u8)1
#define STATE_7 (u8)0
*/
//=======================================================
#define NEGATIVE (s8)-1
#define POSITIVE (s8)1
#define NEGATIVE_SWAP (s8)-2
#define POSITIVE_SWAP (s8)2
#define ERROR (s8)127
#define GPIO_MSK (u8)0x07
//#define ICx_FILTER (u8) 0x0B // 11 <-> 1333 nsec
#define ICx_FILTER (u8) 0x0F // 11 <-> 1333 nsec
#define TIMx_PRE_EMPTION_PRIORITY 2
#define TIMx_SUB_PRIORITY 0
/* if (HALL_SENSORS_PLACEMENT == DEGREES_120)
The sequence of the states is {STATE_5,STATE_1,STATE_3,STATE_2,STATE_6,STATE_4}
else if (HALL_SENSORS_PLACEMENT == DEGREES_60)
the sequence is {STATE_1,STATE_3,STATE_7,STATE_6,STATE_4,STATE_0}*/
// Here is practically assigned the timer for Hall handling
#if defined(TIMER2_HANDLES_HALL)
#define HALL_TIMER TIM2
#elif defined(TIMER3_HANDLES_HALL)
#define HALL_TIMER TIM3
#else // TIMER4_HANDLES_HALL
#define HALL_TIMER TIM4
#endif
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef struct {
u16 hCapture;
u16 hPrscReg;
s8 bDirection;
} SpeedMeas_s;
typedef struct {
u32 wPeriod;
s8 bDirection;
} PeriodMeas_s;
/* Private variables ---------------------------------------------------------*/
volatile SpeedMeas_s SensorPeriod[HALL_SPEED_FIFO_SIZE];// Holding the last captures
vu8 bSpeedFIFO_Index; // Index of above array
vu8 bGP1_OVF_Counter; //由于分频太低导致计数溢出的次数
vu16 hCaptCounter; //捕获中断发生的次数
volatile PeriodMeas_s PeriodMeas;
volatile bool RatioDec;
volatile bool RatioInc;
volatile bool DoRollingAverage;
volatile bool InitRollingAverage;
volatile bool HallTimeOut;
static s16 hElectrical_Angle;
static s16 hRotorFreq_dpp;
#if (defined HALL_SENSORS || defined VIEW_HALL_FEEDBACK)
static s8 bSpeed;
#endif
/* Private function prototypes -----------------------------------------------*/
PeriodMeas_s GetLastHallPeriod(void);
PeriodMeas_s GetAvrgHallPeriod(void);
void HALL_StartHallFiltering(void);
u16 HALL_GetCaptCounter(void);
void HALL_ClrCaptCounter(void);
u8 ReadHallState(void);
/*******************************************************************************
* 函数名 : Hall_HallTimerInit
* 功能描述 : 初始化HALL传感器反馈处理的定时器
* 输入 : 无
* 输出 : 无
* 返回 : 无
*******************************************************************************/
void HALL_HallTimerInit(void)
{
TIM_TimeBaseInitTypeDef TIM_HALLTimeBaseInitStructure;
TIM_ICInitTypeDef TIM_HALLICInitStructure;
NVIC_InitTypeDef NVIC_InitHALLStructure;
GPIO_InitTypeDef GPIO_InitStructure;
#if defined(TIMER2_HANDLES_HALL)
/* 使能GPIOA时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 使能TIM2*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
/* 配置PA00,01 ,02作为Hall传感器输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#elif defined(TIMER3_HANDLES_HALL)
/* 使能TIM3时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* 使能GPIOA时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 使能GPIOB时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
/* 配置PA06,07,PB.00作HALL传感器输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#else // TIMER4_HANDLES_HALL
/* 使能TIM4时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
/* 使能GPIOB时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* 配置PB06,07,08作为Hall传感器输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6, GPIO_Pin_7, GPIO_Pin_8;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
// 清定时器
TIM_DeInit(HALL_TIMER);
TIM_TimeBaseStructInit(&TIM_HALLTimeBaseInitStructure);
/* 设置16位工作范围*/
TIM_HALLTimeBaseInitStructure.TIM_Period = U16_MAX;
TIM_HALLTimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置数字滤波时间分频数
TIM_TimeBaseInit(HALL_TIMER,&TIM_HALLTimeBaseInitStructure);
TIM_ICStructInit(&TIM_HALLICInitStructure);
TIM_HALLICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_HALLICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //每转120电角度,产生一次下降沿。
TIM_HALLICInitStructure.TIM_ICFilter = ICx_FILTER; //所以每产生一次捕获中断,相当于马达转了120电角度。
//但是换向是每60电角度就执行一次,因为三个输入信号
TIM_ICInit(HALL_TIMER,&TIM_HALLICInitStructure); //是XOR后然后输入CHANEL1的。
// Force the HALL_TIMER prescaler with immediate access (no need of an update event)
TIM_PrescalerConfig(HALL_TIMER, (u16) HALL_MAX_RATIO,
TIM_PSCReloadMode_Immediate);
TIM_InternalClockConfig(HALL_TIMER);
//Enables the XOR of channel 1, channel2 and channel3
TIM_SelectHallSensor(HALL_TIMER, ENABLE);
TIM_SelectInputTrigger(HALL_TIMER, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(HALL_TIMER,TIM_SlaveMode_Reset);
// Source of Update event is only counter overflow/underflow
//更新中断源只是计数器上溢或者下溢。
TIM_UpdateRequestConfig(HALL_TIMER, TIM_UpdateSource_Regular);
/* Enable the HALL_TIMER IRQChannel*/
#if defined(TIMER2_HANDLES_HALL)
NVIC_InitHALLStructure.NVIC_IRQChannel = TIM2_IRQn;
#elif defined(TIMER3_HANDLES_HALL)
NVIC_InitHALLStructure.NVIC_IRQChannel = TIM3_IRQn;
#else // TIMER4_HANDLES_HALL
NVIC_InitHALLStructure.NVIC_IRQChannel = TIM4_IRQn;
#endif
NVIC_InitHALLStructure.NVIC_IRQChannelPreemptionPriority =
TIMx_PRE_EMPTION_PRIORITY;
NVIC_InitHALLStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
NVIC_InitHALLStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitHALLStructure);
// Clear the TIMx's pending flags
TIM_ClearFlag(HALL_TIMER, TIM_FLAG_Update + TIM_FLAG_CC1 + TIM_FLAG_CC2 + \
TIM_FLAG_CC3 + TIM_FLAG_CC4 + TIM_FLAG_Trigger + TIM_FLAG_CC1OF + \
TIM_FLAG_CC2OF + TIM_FLAG_CC3OF + TIM_FLAG_CC4OF);
// Selected input capture and Update (overflow) events generate interrupt
//使能2个中断,最好分开2行写。
TIM_ITConfig(HALL_TIMER, TIM_IT_CC1, ENABLE);
TIM_ITConfig(HALL_TIMER, TIM_IT_Update, ENABLE);
TIM_SetCounter(HALL_TIMER, HALL_COUNTER_RESET);
TIM_Cmd(HALL_TIMER, ENABLE);
}
/*******************************************************************************
* ROUTINE Name : HALL_InitHallMeasure
*
* Description : Clear software FIFO where are "pushed" latest speed information
* This function must be called before starting the motor to initialize
* the speed measurement process.
*
* Input : None
* Output : None
* Return : None
* Note : First measurements following this function call will be done
* without filtering (no rolling average).
*******************************************************************************/
void HALL_InitHallMeasure( void )
{
// Mask interrupts to insure a clean intialization
TIM_ITConfig(HALL_TIMER, TIM_IT_CC1, DISABLE);
RatioDec = FALSE;
RatioInc = FALSE;
DoRollingAverage = FALSE;
InitRollingAverage = FALSE;
HallTimeOut = FALSE;
hCaptCounter = 0; //捕获中断发生的次数
bGP1_OVF_Counter = 0; //由于分频太低导致计数溢出的次数
for (bSpeedFIFO_Index=0; bSpeedFIFO_Index < HALL_SPEED_FIFO_SIZE;
bSpeedFIFO_Index++)
{
SensorPeriod[bSpeedFIFO_Index].hCapture = U16_MAX;
SensorPeriod[bSpeedFIFO_Index].hPrscReg = HALL_MAX_RATIO;
SensorPeriod[bSpeedFIFO_Index].bDirection = POSITIVE;
// SensorPeriod[bSpeedFIFO_Index].bDirection = NEGATIVE;
}
// First measurement will be stored in the 1st array location
bSpeedFIFO_Index = HALL_SPEED_FIFO_SIZE-1;
// Re-initialize partly the timer
HALL_TIMER->PSC = HALL_MAX_RATIO; //初始化分频数。800
HALL_ClrCaptCounter();
TIM_SetCounter(HALL_TIMER, HALL_COUNTER_RESET);
TIM_Cmd(HALL_TIMER, ENABLE);
TIM_ITConfig(HALL_TIMER, TIM_IT_CC1, ENABLE);
}
/*******************************************************************************
* ROUTINE Name : HALL_GetSpeed
*
* Description : This routine returns Rotor frequency with [0.1Hz] definition.
* Result is given by the following formula:
* Frotor = K x (Fosc / (Capture x number of overflow)))
* where K depends on the number of motor poles pairs
*
* Input : None
* Output : None
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -