STM32學習筆記——基於正點原子例程編碼器模式小結

STM32學習筆記——基於正點原子例程編碼器模式小結

最近一段時間學習了,STM32f4的編碼器功能,經過自己探索和他人的熱心幫助,對於編碼器模式有了一定了解。STM32f4單片機提供編碼器模式,以便用戶可以直接使用編碼器模式讀出編碼器所傳輸的位置信息,供單片機進行下一步操作。
本文章所使用的編碼器爲直流電機尾部自帶的編碼器。
學習STM32編碼器模式,首先應該知道其模式返回的值所代表的含義是什麼,正交編碼器模式在對應的定時器數據寄存器TIMX->CNT中的值反映的是編碼器所處的“位置”,或者所是角度(個人理解就是其所記錄的脈衝次數),正負號代表編碼器是正轉還是反轉。開始編程之前,首先應該知道自己所用的編碼器的線數(所謂線數,個人理解就是電機轉一圈,所使用的編碼器單獨一相所產生的脈衝數是多少),常見的有130、260、390、780。如果實在不知道自己所用的編碼器的線數,可以在編編好程序後,手動把電機轉一圈,使用串口讀出此時定時器數據寄存器TIMX->CNT中的值然後除以自己所設置的是幾倍頻,對照編碼器常用的線數規格,取接近值。

STM32f4正交編碼器設置步驟

本設置以16位通用定時器TIM4爲例

步驟一:設置初始化結構體變量

    GPIO_InitTypeDef GPIO_InitStructure;//定時器4對應IO端口初始化變量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定時器4初始化變量
    TIM_ICInitTypeDef TIM_ICInitStructure;//定時器4輸入捕獲參數

步驟二:時鐘設置

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//GPIO時鐘設置
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//TIM4時鐘設置

步驟三:GPIO口設置

    GPIO_StructInit(&GPIO_InitStructure); //端口復位,避免干擾
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;//初始化TIM4ch1和ch2通道端口,D12、D13        
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF;//端口複用模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//時鐘頻率100MHZ
    GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD 端口                         

    GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//GPIOD12、D13複用爲TIM4_CH1,CH2

步驟四:TIM4定時器模式設置

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//結構體參數設置設爲默認值
    TIM_TimeBaseStructure.TIM_Period = 520-1;//自動重裝載值爲520,這裏我採用二倍頻技術,編碼器線數爲260  
    TIM_TimeBaseStructure.TIM_Prescaler = 0;//預分頻係數爲1
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//對TIM4初始化

步驟五:TIM4輸入捕獲模式參數設置

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising);//正交編碼器模式,A,B兩相都記錄上升沿跳變,二倍頻技術 
    TIM_ICStructInit(&TIM_ICInitStructure); //結構體參數設置設爲默認值
    TIM_ICInitStructure.TIM_ICFilter = 0;  //濾波次數爲1
    TIM_ICInit(TIM4, &TIM_ICInitStructure);//輸入捕獲初始化
    TIM_ClearFlag(TIM4, TIM_FLAG_Update); //TIM4更新中斷標誌清零

步驟六:其餘參數設置

    TIM_SetCounter(TIM4,0);//TIM4數據寄存器清零
    TIM_Cmd(TIM4, ENABLE); //使能TIM4 

步驟七:讀取函數

//定時器5中斷服務函數
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //是否產生更新(溢出)中斷
	{
  printf("\\n編碼器值爲:%d\n",TIM4->CNT);
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清空TIM5中斷標誌位
}

整體代碼

    GPIO_InitTypeDef GPIO_InitStructure;//定時器4對應IO端口初始化變量
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定時器4初始化變量
    TIM_ICInitTypeDef TIM_ICInitStructure;//定時器4輸入捕獲參數
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//GPIO時鐘設置
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//TIM4時鐘設置

    GPIO_StructInit(&GPIO_InitStructure); //端口復位,避免干擾
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;//初始化TIM4ch1和ch2通道端口,D12、D13        
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF;//端口複用模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空模式

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//時鐘頻率100MHZ
    GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD 端口                         

    GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
    GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);//GPIOD12、D13複用爲TIM4_CH1,CH2

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//結構體參數設置設爲默認值
    TIM_TimeBaseStructure.TIM_Period = 520-1;//自動重裝載值爲520,這裏我採用二倍頻技術,編碼器線數爲260  
    TIM_TimeBaseStructure.TIM_Prescaler = 0;//預分頻係數爲1
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//對TIM4初始化

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising);//正交編碼器模式,A,B兩相都記錄上升沿跳變,二倍頻技術 
    TIM_ICStructInit(&TIM_ICInitStructure); //結構體參數設置設爲默認值
    TIM_ICInitStructure.TIM_ICFilter = 0;  //濾波次數爲1
    TIM_ICInit(TIM4, &TIM_ICInitStructure);//輸入捕獲初始化
    TIM_ClearFlag(TIM4, TIM_FLAG_Update); //TIM4更新中斷標誌清零

    TIM_SetCounter(TIM4,0);//TIM4數據寄存器清零
    TIM_Cmd(TIM4, ENABLE); //使能TIM4

//定時器5中斷服務函數
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //是否產生更新(溢出)中斷
	{
  printf("\\n編碼器值爲:%d\n",TIM4->CNT);
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清空TIM5中斷標誌位
}

本文之前採用四倍頻設置,但問過小夥伴後,小夥伴說官網的四倍頻程序有問題,建議我我採用二倍頻設置,自己也經過實驗驗,發現當正交編碼器模式設置四倍頻時,電機轉一圈所得的脈衝數是二倍頻模式的一半,二倍頻爲精度最高的模式,所以設置爲二倍頻設置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章