目录
2.1、TIM_EncoderInterfaceConfig()
一、编码器接口介绍
编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度。
两个输入引脚借用了输入捕获的通道1和通道2,且无法使用通道3/4,。
1.1、电路部分
1.2、编码器的基本配置流程
1.3、计数方向与编码信号
该表与下图是关系对应的
二、代码配置
2.1、TIM_EncoderInterfaceConfig()
//定时器编码器接口配置函数
//参数1:选择定时器;参数2:选择定时器模式;参数3/4分别为选择通道1/2的电平极性
TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);
2.2、Encoder_Init()配置
2.2.1、开启时钟部分
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启时钟,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟,选择GPIOkou
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//选择上拉输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
2.2.2、时基单元部分
TIM_InternalClockConfig(TIM3);//初始化时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//指定参数分频值(选择1分频),
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择技术模式;
TIM_TimeBaseInitStructure.TIM_Period=65536-1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=1-1; //PSC 不分频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //配置时基单元
2.2.3、输入捕获单元的配置
由2.2.3、图1可以看出编码器接口仅用到输入捕获单元的部分配置,因此输入捕获单元不需要像2.2.3、图2那样全部配置。因此下图中的28、29代码可以略去,但是略去后结构体配置不完整,为避免出现不确定值造成不必要的麻烦,所以需要用到 24 条代码,为结构体赋初始值。其实第 27 条代码也可以删去,因为接口配置中会有相关函数配置极性。
TIM_ICInitTypeDef TIM_ICINitstructure;
TIM_ICStructInit(&TIM_ICINitstructure);//结构体TIM_ICINitstructure赋初始值
TIM_ICINitstructure.TIM_Channel=TIM_Channel_1; //选择通道,本例程中使用的是TIM3的通道1
TIM_ICINitstructure.TIM_ICFilter=0xF;//配置输入捕获的滤波器,数值大,滤波效果越好
TIM_ICINitstructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//极性选择 上升沿or下降沿,
以下是配置两个通道,蓝色部分是通道1,红色部分为通道2
以下是给部分最终代码。已经删去关于极性配置代码。
TIM_ICInitTypeDef TIM_ICINitstructure;
TIM_ICStructInit(&TIM_ICINitstructure);//结构体TIM_ICINitstructure赋初始值
TIM_ICINitstructure.TIM_Channel=TIM_Channel_1; //选择通道,本例程中使用的是TIM3的通道1
TIM_ICINitstructure.TIM_ICFilter=0xF; //配置输入捕获的滤波器,数值大,滤波效果越好,
TIM_ICInit(TIM3,&TIM_ICINitstructure);
TIM_ICINitstructure.TIM_Channel=TIM_Channel_2; //选择通道,本例程中使用的是TIM3的通道1
TIM_ICINitstructure.TIM_ICFilter=0xF; //配置输入捕获的滤波器,数值大,滤波效果越好
TIM_ICInit(TIM3,&TIM_ICINitstructure);
2.2.4、编码器接口配置
该部分仅需要用到函数 TIM_EncoderInterfaceConfig()便可配置
//定时器编码器接口配置函数
//参数1:选择定时器;参数2:选择定时器模式;参数3/4分别为选择通道1/2的电平极性
该函数的参数3和参数4便起到替代 2.2.3、图3的第27、31条函数的作用。
TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);
TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
TIM_Cmd(TIM3,ENABLE);//开启定时器
2.2.5、Encoder_Init()完整代码
void Encoder_Init()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启时钟,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟,选择GPIOkou
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//选择上拉输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);//初始化时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//指定参数分频值(选择1分频)
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择技术模式;
TIM_TimeBaseInitStructure.TIM_Period=65536-1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=1-1; //PSC 预分频不分频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //配置时基单元
TIM_ICInitTypeDef TIM_ICINitstructure;
TIM_ICStructInit(&TIM_ICINitstructure);//结构体TIM_ICINitstructure赋初始值
TIM_ICINitstructure.TIM_Channel=TIM_Channel_1; //选择通道,本例程中使用的是TIM3的通道1
TIM_ICInit(TIM3,&TIM_ICINitstructure);
TIM_ICINitstructure.TIM_Channel=TIM_Channel_2; //选择通道,本例程中使用的是TIM3的通道1
TIM_ICInit(TIM3,&TIM_ICINitstructure);
TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
TIM_Cmd(TIM3,ENABLE);//开启定时器
}
2.2.5、实现速度测试
//读取CNT的值后将其清零
int16_t Encoder_Get(void)
{
int16_t Temp;
Temp=TIM_GetCounter(TIM3);//获取TIMx计数器值;
TIM_SetCounter(TIM3,0);//设置TIMx计数器寄存器值
return Temp;
}
while(1)
{
OLED_ShowSignedNum(1,7,Encoder_Get(),5);
Delay_ms(1000);
}
首先我们使用以上的代码获取CNT的值然后在while(1)中每1s获取一次CNT的值,那么读取的CNT值即为速度(以上代码非演示代码)。但是在主函数中需要慎用Delay()。所以们需要使用中断函数配置。以下即为中断代码,对于具体多久进一次中断需要查看中断函数的ARR以及PSC参数。
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
Speed=Encoder_Get();
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}