ROS小車搭建之編碼器值得獲取

好久沒有更新博客了,這節主要給大家講解一下ROS小車STM32F4控制器通過STM32定時器的編碼器模式獲取編碼的值。

STM32F4定時器具有編碼器功能的包括兩個高級定時器1、8和四個通用定時器2、3、4、5。這節主要使用定時器5進行講解。

假如對定時器5的編碼器引腳對應不太明白的可以使用STM32CubeMx軟件進行查看,如下圖可以看到定時器5的編碼器接口是在PA0和PA1上。

弄清楚引腳後開始編寫代碼,文章使用的是庫函數版本進行配置,

timer.c

#include "timer.h"
/* total value since startup */
int32_t position;
/* last read of timer */
uint16_t last_timer;
/* last difference between timer reads */
int16_t last_timer_diff;
//arr:自動重裝值(TIM2,TIM5是32位的!!) 0xffff
//psc:時鐘預分頻數                    0
//
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
    TIM_ICInitTypeDef  TIM_ICInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  	  //TIM5時鐘使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 	//使能PORTA時鐘	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //GPIOA0
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//複用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推輓複用輸出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA0

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //PA0複用位定時器5
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM5); //PA0複用位定時器5
	  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定時器分頻
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上計數模式
	TIM_TimeBaseStructure.TIM_Period=arr;   //自動重裝載值
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
    TIM_EncoderInterfaceConfig(TIM5, 
    TIM_EncoderMode_TI12,TIM_ICPolarity_BothEdge,TIM_ICPolarity_BothEdge);
    TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_ICFilter = 6; 
	TIM_ICInit(TIM5, &TIM_ICInitStructure);
	TIM_ClearFlag(TIM5, TIM_FLAG_Update); 
	TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE); 
	TIM_SetCounter(TIM5, 0);
	TIM_Cmd(TIM5, ENABLE); 	
}
int32_t read()
{
	uint16_t timer_value = TIM_GetCounter(TIM5);
	last_timer_diff = timer_value - last_timer;
	last_timer = timer_value;
	position += (int32_t) last_timer_diff;

	return position;
}

 

timer.h

#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
void TIM5_CH1_Cap_Init(u32 arr,u16 psc);
int32_t read();
#endif

 

計數方向與編碼器信號的關係如下圖:

編碼器的詳細配置請參考STM32F4XX中文參考手冊中的15.3.12通用定時器(TIM2到TIM5)編碼器接口模式,看一下相關寄存器該怎麼配置。獲取編碼器的值直接調用read()函數即可。

寫在後面的話:目前正在把之前寫好的底盤工程移植到FreeTROS中,因爲跑裸機消息發送的頻率不夠,導致了上層里程計更新頻率不夠,建圖出現較大誤差的問題,後期也會和大家分享,希望大家多多關注我的博客。

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