⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stm32f10x_hall.c

📁 ARM_CORTEX-M3应用实例开发详解光盘
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************** (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 + -