BLDC開發筆記3.霍爾接口與觸發換相


希望看過的各位對錯誤之處可以幫忙指正。

長期更新。

霍爾接口初始化

使用高級控制定時器(TIM1或TIM8)產生PWM信號驅動馬達時,可以用另一個通用TIMx(TIM2、TIM3、 TIM4或TIM5)定時器作為“接口定時器”來連接霍爾傳感器 。這里選用定時器3。

stm32的通用定時器內部集成了針對霍爾/編碼器信號處理的電路。如下圖:

工作過程

  1. TIMx_CH1、TIMx_CH2和TIMx_CH3三個引腳接受到的霍爾信號,經過輸入異或(XOR)功能,傳到輸入通道TI1
  2. 信號從TI1的經過輸入濾波器(配置濾波長度)和邊沿檢測器(輸入觸發有效極性,這里配置為雙極性有效,即上升沿和下降沿都能觸發)后產生脈沖信號TI1F_ED,經過選擇器后作為TRC輸入,再將TRC作為輸入捕獲通道IC1的輸入信號。IC1PS就是計數器的捕獲觸發信號(脈沖),決定什么時候將計數器的值傳進輸入捕獲寄存器。整個過程就是映射過程。
  3. 配置時基,內部時鍾分頻后作為計數器時鍾,將從模式控制器配置為復位模式,每當3個輸入之一變化時,計數器從新從0開始計數,計數到下一個變化開始為止,這個計數器值CNT就反映了兩個霍爾狀態之間的時間間隔,通過這個值我們可以計算出電機的轉速信息。

注意,TI1F_ED是一個脈沖,根據這點之后觸發也是脈沖觸發。如下圖,當異或后信號發生跳變,都會產生一個脈沖 TI1F_ED。

GPIO初始化

先在頭文件進行宏定義

#define HALL_TIMx                        TIM3
#define HALL_TIM_APBxClock_FUN           RCC_APB1PeriphClockCmd
#define HALL_TIM_CLK                     RCC_APB1Periph_TIM3
#define HALL_TIM_PERIOD                  0xFFFF           //ARR,計數周期,配置為最大65535
#define HALL_TIM_PRESCALER               (72-1)           //預分頻系數為72
#define HALL_TIM_Channel_x               TIM_Channel_1    //通道1

#define HALL_TIM_GPIO_REMAP              GPIO_FullRemap_TIM3  //引腳重映射
#define HALL_TIM_GPIO_CLK                RCC_APB2Periph_GPIOC
#define HALL_TIM_CH1_PIN                 GPIO_Pin_6
#define HALL_TIM_CH1_GPIO                GPIOC
#define HALL_TIM_CH2_PIN                 GPIO_Pin_7
#define HALL_TIM_CH2_GPIO                GPIOC
#define HALL_TIM_CH3_PIN                 GPIO_Pin_8
#define HALL_TIM_CH3_GPIO                GPIOC

#define HALL_TIM_IRQn                    TIM3_IRQn
#define HALL_TIM_IRQHANDLER              TIM3_IRQHandler

需要注意的是,時基編程中,要將TIMx_ARR置為其最大值(計數器必須通過TI1的變化清零)。設置預分頻器得到
的最大計數器周期,它需要長於霍爾傳感器上的兩次變化的時間間隔,不然就會發生溢出,這里進行72分頻后,計數器時鍾是1Mhz,所以計數周期是1us*65535=65.535ms。

GPIO初始化配置

將定時器3的3個GPIO初始化,配置為上拉輸入模式

void HALL_TIMx_GPIO_Init(void)
{
  //GPIO初始化結構體
  GPIO_InitTypeDef GPIO_InitStructure;
  
  //打開GPIOC和復用功能時鍾
  RCC_APB2PeriphClockCmd(HALL_TIM_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE); 
  
  //GPIOC_6初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH1_PIN;  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  //上拉輸入
  GPIO_Init(HALL_TIM_CH1_GPIO, &GPIO_InitStructure);
  
  //GPIOC_7初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH2_PIN; 
  GPIO_Init(HALL_TIM_CH2_GPIO, &GPIO_InitStructure);
  
  //GPIOC_8初始化
  GPIO_InitStructure.GPIO_Pin = HALL_TIM_CH3_PIN; 
  GPIO_Init(HALL_TIM_CH3_GPIO, &GPIO_InitStructure);

  //引腳重映射
  GPIO_PinRemapConfig(HALL_TIM_GPIO_REMAP,ENABLE);  
}

霍爾接口配置

  1. 配置定時器3的時基
  2. 將定時器3配置為輸入捕獲模式,將IC1映射到TRC
  3. 從模式控制器配置為復位模式
  4. 使能觸發中斷
void HALL_TIMx_Configuration(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;  //時基初始化結構體
	TIM_ICInitTypeDef TIM_ICInitStruct;  //輸入捕獲初始化結構體
		
	//打開定時器3時鍾
	HALL_TIM_APBxClock_FUN(HALL_TIM_CLK,ENABLE);
	//時基參數配置
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;  //時鍾分割:TDTS = TCK_INT ,采樣頻率=72M
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_CenterAligned1;  //中心對齊模式
	TIM_TimeBaseInitStruct.TIM_Period=HALL_TIM_PERIOD;  //重裝值,計數周期
	TIM_TimeBaseInitStruct.TIM_Prescaler=HALL_TIM_PRESCALER;  //預分頻系數
	//時基初始化
	TIM_TimeBaseInit(HALL_TIMx,&TIM_TimeBaseInitStruct);
	
	//輸入捕獲通道1配置
	TIM_ICInitStruct.TIM_Channel=HALL_TIM_Channel_x;  //通道1
	TIM_ICInitStruct.TIM_ICFilter=0x00;  //濾波長度:0
	TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_BothEdge;  //上升沿和下降沿
	TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;  //配置輸入信號分頻,不分頻
	TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_TRC;  //將IC1映射到 TRC上
	TIM_ICInit(HALL_TIMx,&TIM_ICInitStruct);  //輸入捕獲初始化
	
        //配置中斷優先級
        HALL_IT_Configuration();  
	
	//使能Timx霍爾傳感器接口,實際上就是完成將CH1、CH2和CH3異或輸入
	TIM_SelectHallSensor(HALL_TIMx,ENABLE);  
	//輸入觸發源選擇,選擇TI1F_ED
	TIM_SelectInputTrigger(HALL_TIMx, TIM_TS_TI1F_ED);
	
	//從模式選擇,復位模式
	TIM_SelectSlaveMode(HALL_TIMx, TIM_SlaveMode_Reset); 
	//主從模式選擇
	TIM_SelectMasterSlaveMode(HALL_TIMx, TIM_MasterSlaveMode_Enable); 
	
	//允許觸發中斷
	TIM_ITConfig(HALL_TIMx, TIM_IT_Trigger, ENABLE); 
	
	//使能定時器
	TIM_Cmd(HALL_TIMx, ENABLE);
	
	//清除TIMx中斷標志位
	TIM_ClearITPendingBit (HALL_TIMx,TIM_IT_Trigger);
	
}

其中,中斷優先級配置函數為

void HALL_IT_Configuration(void)
{
    //NVIC初始化結構體
    NVIC_InitTypeDef NVIC_InitStruct;
  
    //中斷優先級配置
    NVIC_InitStruct.NVIC_IRQChannel=HALL_TIM_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
    NVIC_Init(&NVIC_InitStruct);
}

中斷優先級我將霍爾觸發中斷配置為最高級。

霍爾接口總初始化函數

就是調用我們前面寫的兩個配置函數。

void HALL_TIMx_Init(void)
{
    HALL_TIMx_GPIO_Init();
    HALL_TIMx_Configuration();	
}

中斷服務函數

使能了中斷,不要忘記編寫中斷服務函數,我習慣將其放在main.c里面,也看過放在 it.c里面

值得一提的是,通用定時器中斷類型並不體現在中斷服務函數名稱上,通用定時器的中斷服務函數名就只有一個,可以在啟動文件里面輕易找到她,她是通過判斷中斷標志位,區分哪一種中斷。

void HALL_TIM_IRQHANDLER(void)
{
  if(TIM_GetITStatus(TIM3,TIM_IT_Trigger)!=RESET)
  {
     HALL_TIMx_Callback();  //讀取霍爾信號並換相
     TIM_ClearITPendingBit(TIM3,TIM_IT_Trigger);  //清除觸發中斷標志位
  }
}

需要提醒的是,這個中斷服務函數里面一定不能有任何費時的操作,假設電機高速旋轉,存在一個操作需要時間大於霍爾兩個狀態之間切換時間(在上一個PWM輸出和慣性的影響下),那么存在漏步問題,電機將不按照順序旋轉下去,所以費時操作會影響下一個霍爾狀態的讀取,導致PWM輸出不正確。

霍爾信號讀取

可以看到,中斷服務函數這里調用了函數 HALL_TIMx_Callback();她的作用是判斷3個輸入引腳上的電平,並將其合成霍爾組合信號,根據這個組合信號,當霍爾信號每一次變化,產生中斷時,我們就可以按照霍爾換相表,調用在六步PWM輸出里面寫的換相函數BLDC_PHASE_CHANGE(pinstate);。

void HALL_TIMx_Callback(void)
{
	        uint8_t pinstate=0;
	
		if((HALL_TIM_CH1_GPIO->IDR & HALL_TIM_CH1_PIN) != (uint32_t)Bit_RESET)  //CH1狀態獲取
		{
			pinstate |= 0x01;
		}
		if((HALL_TIM_CH2_GPIO->IDR & HALL_TIM_CH2_PIN) != (uint32_t)Bit_RESET)  //CH2狀態獲取
		{
			pinstate |= 0x02;
		}
		if((HALL_TIM_CH3_GPIO->IDR & HALL_TIM_CH3_PIN) != (uint32_t)Bit_RESET)  //CH3狀態獲取
		{
			pinstate |= 0x04;
		}
	        //Usart_SendByte(pinstate);  //把霍爾換步信號發送到串口上,不測試時將其注釋掉
	        BLDC_PHASE_CHANGE(pinstate); //調用換相函數 
}

開環波形測試

接上BLDC,我使用的是24V的鼓風機,將三相逆變電路板通電測試,通過示波器看其中兩路波形(只有兩路示波器)。

個人分析:可以看到,在切換通道時候出現了較高的反向電動勢,但由於MOS管體二極管將其鉗位在電源電壓。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM