编码器(encoder)是将信号或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。按照外形可以分为实心轴和空心轴;按照工作原理编码器可分为增量式和绝对式两类。增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。
增量型:就是每转过单位的角度就发出一个脉冲信号(也有发正余弦信号,然后对其进行细分,斩波出频率更高的脉冲),通常为A相、B相、Z相输出,A相、B相为相互延迟1/4周期的脉冲输出,根据延迟关系可以区别正反转,而且通过取A相、B相的上升和下降沿可以进行2或4倍频;Z相为单圈脉冲,即每圈发出一个脉冲。
绝对值型:就是对应一圈,每个基准的角度发出一个唯一与该角度对应二进制的数值,通过外部记圈器件可以进行多个位置的记录和测量。
单相联接:只有A相用于测速,方向靠DIR判断
A、B两相联接,可判断正反向和测速。
A、B、Z三相联接,用于带参考位修正的位置测量。
我这里用的是单相的龙邱512线的,每转一圈编码器输出512个脉冲 ,根据这个编码器输出脉冲就可以用单片机IO测出脉冲个数,进而判断编码器转了几圈以及速度。
编码器接线:编码器A相接单片机的TIM5_CH1,对应接口为PA0,编码器的DIR可以接PA1读取正转反转电平。
void TIM5_CH1_Input_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能TIM5时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//管脚设置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //设置下拉输入模式
GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道1
TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获极性
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//直接映射到TI1
TIM_ICInit(TIM5,&TIM_ICInitStructure);
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;//中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM5,ENABLE); //使能定时器
}
/*******************************************************************************
* @brief TIM5_CH1中断函数
* @param 无
* @retval 无
*******************************************************************************/
void TIM5_IRQHandler(void)
{
if((TIM5_CH1_CAPTURE_STA&0x80)==0) //还未成功捕获
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update)) //发生更新中断
{
if(TIM5_CH1_CAPTURE_STA&0X40)//捕获到了高电平
{
if((TIM5_CH1_CAPTURE_STA&0x3f)==0x3f) //高电平时间太长
{
TIM5_CH1_CAPTURE_STA|=0x80; //标志一次捕获成功
TIM5_CH1_CAPTURE_VAL=0xffff;
}
else
{
TIM5_CH1_CAPTURE_STA++;
}
}
}
if(TIM_GetITStatus(TIM5,TIM_IT_CC1)) //发生捕获中断
{
if(TIM5_CH1_CAPTURE_STA&0X40)//捕获到了低电平
{
TIM5_CH1_CAPTURE_STA|=0x80; //成功捕获一次高电平
TIM5_CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置上升沿捕获
}
else
{
TIM5_CH1_CAPTURE_STA=0;
TIM5_CH1_CAPTURE_VAL=0;
TIM5_CH1_CAPTURE_STA|=0x40; //捕获到高电平 标志
TIM_Cmd(TIM5,DISABLE);
TIM_SetCounter(TIM5,0); //定时器初值为0
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置下降沿捕获
TIM_Cmd(TIM5,ENABLE);
}
}
}
TIM_ClearITPendingBit(TIM5,TIM_IT_CC1|TIM_IT_Update);
}
main函数死循环捕获脉冲就行
while(1)
{
if(TIM5_CH1_CAPTURE_STA&0x80) //成功捕获
{
temp=temp++;
TIM5_CH1_CAPTURE_STA=0; //开始下一次捕获
}
OLED_ShowSignedNum(1, 7, temp, 5);
}