stm32编码器测速
生活随笔
收集整理的這篇文章主要介紹了
stm32编码器测速
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
摘要:編碼器是一種將角位移或者角速度轉換成一串電數字脈沖的旋轉式傳感器。編碼器又分為光電編碼器和霍爾編碼器。
霍爾編碼器是有霍爾碼盤和霍爾元件組成?;魻柎a盤是在一定直徑的圓板上等分的布置有不同的磁極?;魻柎a盤與電動機同軸,電動機旋轉時,霍爾元件檢測輸出若干脈沖信號,為判斷轉向,一般輸出兩組存在一定相位差的方波信號。
采集數據方式:
第一種軟件技術直接采用外部中斷進行采集,根據AB相位差的不同可以判斷正負。
第二種硬件技術直接使用定時器的編碼器模式。
這里采用第二種。也是大家常說的四倍頻,提高測量精度的方法。其實就是把AB相的上升沿和下降沿都采集而已,所以1變4。自己使用外部中斷方式實現就比較占用資源了,所以不建議使用。
速度計算方法:
真實的物理轉速:
電機轉動一圈的脈沖數:num1 單位:個
單位時間:t 單位:秒
單位時間內捕獲的脈沖變化數:num2 單位:個 (反應電機正反轉)
電機輪子半徑:r 單位:m
圓周率:pi 單位:無
速度:speed 單位: mm/s
因為半徑用的是m為單位,速度為mm所以需要乘以1000。
代碼:(使用TIM2和TIM4兩個定時器來測兩個輪子的速度)
將編碼器AB相使用的引腳設置成定時器的編碼器模式,我們根據TIMx->CNT寄存器數據的變化,計算出單位時間內,脈沖的變化值。
然后在定時器中斷服務函數中進行速度計算。
#include "encoder.h"/************************************************************************** 函數功能:把TIM2初始化為編碼器接口模式 入口參數:無 返回 值:無 **************************************************************************/ void Encoder_Init_TIM2(void) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定時器2的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure); //根據設定參數初始化GPIOATIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //預分頻器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數器自動重裝值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //選擇時鐘分頻:不分頻TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上計數 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用編碼器模式3TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = 10;TIM_ICInit(TIM2, &TIM_ICInitStructure);TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除TIM的更新標志位TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//Reset counterTIM_SetCounter(TIM2,0);//===============================================TIM2->CNT = 0x7fff;//===============================================TIM_Cmd(TIM2, ENABLE); } /************************************************************************** 函數功能:把TIM4初始化為編碼器接口模式 入口參數:無 返回 值:無 **************************************************************************/ void Encoder_Init_TIM4(void) {TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定時器4的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入GPIO_Init(GPIOB, &GPIO_InitStructure); //根據設定參數初始化GPIOBTIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 預分頻器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //設定計數器自動重裝值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //選擇時鐘分頻:不分頻TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上計數 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用編碼器模式3TIM_ICStructInit(&TIM_ICInitStructure);TIM_ICInitStructure.TIM_ICFilter = 10;TIM_ICInit(TIM4, &TIM_ICInitStructure);TIM_ClearFlag(TIM4, TIM_FLAG_Update); //清除TIM的更新標志位TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//Reset counterTIM_SetCounter(TIM4,0);//===============================================TIM4->CNT = 0x7fff;//===============================================TIM_Cmd(TIM4, ENABLE); }/************************************************************************** 函數功能:讀取編碼器脈沖差值,讀取單位時間內的脈沖變化值 入口參數:TIM_TypeDef * TIMx 返回 值:無 **************************************************************************/ s16 getTIMx_DetaCnt(TIM_TypeDef * TIMx) {s16 cnt;cnt = TIMx->CNT-0x7fff;TIMx->CNT = 0x7fff;return cnt; }/************************************************************************** 函數功能:計算左右輪速 入口參數:int *leftSpeed,int *rightSpeed 返回 值:無//計算左右車輪線速度,正向速度為正值 ,反向速度為負值,速度為乘以1000之后的速度 mm/s//一定時間內的編碼器變化值*轉化率(轉化為直線上的距離m)*200s(5ms計算一次) 得到 m/s *1000轉化為int數據一圈的脈沖數:左:1560右:1560輪子半徑:0.03m輪子周長:2*pi*r一個脈沖的距離:左:0.000120830m右:0.000120830m速度分辨率:左: 0.0240m/s 右: 0.0240m/s 200 5ms的倒數1000 擴大分辨率 **************************************************************************/void Get_Motor_Speed(int *leftSpeed,int *rightSpeed) {//5ms測速 5ms即這里說的單位時間 *leftSpeed = getTIMx_DetaCnt(TIM4)*1000*200*0.000120830; *rightSpeed = getTIMx_DetaCnt(TIM2)*1000*200*0.000120830; }main.c
#include "sys.h"//====================自己加入的頭文件=============================== #include "delay.h" #include "led.h" #include "encoder.h" #include "usart3.h" #include "timer.h" #include <stdio.h> //===================================================================int leftSpeedNow =0; int rightSpeedNow =0;int main(void) { GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//禁用JTAG 啟用 SWDMY_NVIC_PriorityGroupConfig(2); //=====設置中斷分組delay_init(); //=====延時函數初始化LED_Init(); //=====LED初始化 程序燈 usart3_init(9600); //=====串口3初始化 藍牙 發送調試信息Encoder_Init_TIM2(); //=====初始化編碼器1接口Encoder_Init_TIM4(); //=====初始化編碼器2接口TIM3_Int_Init(50-1,7200-1); //=====定時器初始化 5ms一次中斷while(1){printf("L=%d,R=%d\r\n",leftSpeedNow,rightSpeedNow);delay_ms(15);} }//5ms 定時器中斷服務函數 void TIM3_IRQHandler(void) //TIM3中斷 {if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查指定的TIM中斷發生與否:TIM 中斷源 {TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx的中斷待處理位:TIM 中斷源 Get_Motor_Speed(&leftSpeedNow,&rightSpeedNow);Led_Flash(100);} }總結
以上是生活随笔為你收集整理的stm32编码器测速的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 未能找到该服务器列表,未能找到使用此主机
- 下一篇: win10下编译安装ncnn