STM32 中的编码器模式:带方向/正交编码
STM32编码器模式
1、编码器介绍
- 输出脉冲线数:1024线:编码器每旋转一周输出的脉冲的个数,这个数据就是你在编写的定时器的重装载值。
- 带方向的编码器只有一路的脉冲输出,另外一路就是编码器的正反转的信号,零位信号就是编码器的机械零位。
- 正交编码器两路的脉冲输出,在判断电机的正反转时,是更加A、B两相的波形来的,其实就是看哪路波形超前,这里用32的定时器编码器功能就只需要去查计数器的方向位来判断电机的正反转。
- 引脚说明
2、脉冲计数对应电机速度的数据两种处理方式
(1) 定时器中断法,计算电机的圈数(过程小题大做,不推荐)
(1)脉冲计数法,直接根据单位时间内所采集到的脉冲数作为电机的转速(更加精准,推荐)
3、STM32定时器编码器模式理论分析
(1)定时器编码器模式选择
(2)定时器编码器输入极性的选择

(3)定时器编码器输入极性的寄存器配置
CC1S=’01’ (TIMx_CCMR1寄存器,IC1FP1映射到TI1)
CC2S=’01’ (TIMx_CCMR1寄存器,IC2FP2映射到TI2)
CC1P=’0’ (TIMx_CCER寄存器,IC1FP1不反相,IC1FP1=TI1)
CC2P=’0’ (TIMx_CCER寄存器,IC2FP2不反相,IC2FP2=TI2)
SMS=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).
CEN=’1’ (TIMx_CR1寄存器,计数器使能)

4、结合手册函数刨析库函数
(1)STM32定时器编码器模式的库函数配置代码
/*TIM2初始化为编码器接口*/
void Encoder_Init_TIM2(void)
{
//结构体变量的创建
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//RCC时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
//编码器引脚的配置,对于定时器的通道管脚在用户手册上的==8.3.7定时器复用功能重映射==
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口选择
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
//定时器的基本配置,这里主要介绍定时器的编码器模式,不做过多解释
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = 0xffff; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//编码器模式选择与配置
//参数一TIMx:定时器的选择
//参数二TIM_EncoderMode:编码器模式的选择
//参数三TIM_IC1Polarity:通道一的极性选择
//参数四TIM_IC2Polarity:通道二的极性选择
//具体配置->正交编码器:配置如下
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
//带方向的编码器配置如下->区别只在于带方向的编码器只有一个脉冲输入,而正交编码器有两个脉冲输入
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_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 counter
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);
}
(2)刨析
- 转到
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
函数下可以看到如下代码:
/* Get the TIMx SMCR register value */
tmpsmcr = TIMx->SMCR;
/* Get the TIMx CCMR1 register value */
tmpccmr1 = TIMx->CCMR1;
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;

5、编码器速度的读取
//配置定时器1每5毫秒中断一次,在中断函数中读取编码器数值
void Time1_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStrure;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//定时器的基本配置
TIM_TimeBaseStrure.TIM_Period = 1000-1;//计数的次数
TIM_TimeBaseStrure.TIM_Prescaler = 7200-1;//控制频率72000000/7200=10000;频率=10000HZ
TIM_TimeBaseStrure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStrure.TIM_ClockDivision = 0;
TIM_TimeBaseStrure.TIM_RepetitionCounter = 0;//重复计数次数
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStrure);
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清空中断标志位
TIM_ITConfig(TIM1,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//开启中断更新和触发中断源
NVIC_InitStruct.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM1,ENABLE);
}
int Read_Encoder(void)
{
int value_1;
value_1=(int)TIM_GetCounter(TIM2);
TIM_SetCounter(TIM2,0);
return value_1;
}
void TIM1_UP_IRQHandler()
{
int circle_count ;
if(TIM_GetITStatus(TIM1,TIM_IT_Update) != RESET)
{
circle_count = Read_Encoder();
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清空中断标志位
}
}