好久没有更新博客了,这节主要给大家讲解一下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中,因为跑裸机消息发送的频率不够,导致了上层里程计更新频率不够,建图出现较大误差的问题,后期也会和大家分享,希望大家多多关注我的博客。
版权声明:本文为qq_36349536原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。