一篇文章带你了解——EC11编码器
本文旨在帮助大家快速深入了解EC11编码器的原理及应用,并提供单片机驱动EC11基础代码和消抖代码供大家学习。
一,什么是EC11编码器
实物图:
封装图:
引脚介绍:
A、B、C:编码器数据引脚,C为公共端,AB为信号端。
D、E:按键引脚,相当于按键开关。
6,7:固定编码器引脚,不接入电路。
二,模块原理
内部原理:(请仔细阅读以下说明,方便您快速了解EC11编码器)
简单的原理如上图所示,C作为公共端,我们可以根据实际的需求来设置,一般情况下我们都接地,这样方便我们进行代码调试。AB为数据端,AB转动存在相位差,所以通过AB的关系来获取编码器的转向信息,一般来说A在前B在后是正转即顺时针,这里的前后是指电平的变化前后,编码器实际就是一个开关,只是我们使用一个旋转开关同时控制两个输出而已。
在了解编码器的内部原理之前,我们应该了解一下什么是编码器的档数(或者说定位),正常的EC11编码器有15档、20档等,这里的档可以理解为,我们转动一圈,开关内部闭合与打开多少次,由原理图可知,我们编码器的内部实际上是一个单刀开关,转动一次之后,开关改变一次状态,A与B的电平就发生翻转。
重点来了,为了区分我们编码器转动的方向,即是正转还是翻转,这跟内部的机械结构有关,一般来说,正转时A相位快于B,反转时A相位慢于B,这样我们就可以通过A的跳变沿结合B的电平来确定正转与反转了。相比较于电位器的读取AD值,他的作用在于可以不停的旋转,而且只有发生旋转的时候,AB才会发生改变。
除此之外,我们还要了解EC11的独立按键作用,我看很多的文章都没提高EC11这个独立按键,其实这个是EC11相比较与其他的按键的精华之处,在于我们通过按键选择模式,然后旋转来确定大小,在实际的应用当中非常广泛,例如我们的热风机调温,就是使用到这个,还有电子手表也在广泛的使用该器件,只是型号不同而已。
在研究EC11的时序之前首先要了解一点,EC11按旋转的输出动作可以分为两种。一种是两定位一脉冲,即转两格A、B对C端输出一个完整脉冲(转一格就只是由低电平->高电平或由高电平->低电平);另一种一定位一脉冲,即就是转一格,A、B对C端输出一个完整脉冲。大多数的编码器都是一定位一脉冲。
如果是一定位一脉冲的类型,不转动的时候A,B于C端都不导通。如果是两定位一脉冲的类型,会有A,B与C端导通和A,B与C端不导通两种情况。稍微转一下转轴然后测量,若A,B与C端都导通,那么就是两定位一脉冲类型。虽然这种EC11无步进手感,但是大多数也是转一圈输出15脉冲(30格)或20脉冲(20格)的类型。
三,电路连接
AB引脚其中一个接入外部中断,另一个接入普通的IO口,C引脚直接接地。
DE引脚其中一个接入普通IO口,另一个接地。
有上拉电阻
初始化的时候,IO不需要要配置内部上拉电阻,即配置普通模式(准双向、双向模式)即可。这个R4、R5、R6非必要,可以不用接入电路。
无上拉电阻
初始化的时候,IO要配置内部上拉电阻,否则无法编码。
四,代码编写
使用STC15单片机为例,将A引脚接到P32,B引脚接到P33,开始外部中断1,选择下降沿触发,使用P32作为中断输入。
基本的时序:
工作流程是:旋转编码器P32口下降沿触发外部中断1判断P33的极性确定正反转
unsigned char num;
void INT0_Init()
{
IT0=1; //下降沿触发
IE0=0; //清楚中断标志位
EX0=1; //打开外部中断请求
EA=1; //打开中断总开关
}
void INTO_Routine() interrupt 0
{
if(P33) //逆时针
{
num--;
}
else //顺时针
{
num++;
}
}
这里的顺时针和逆时针可由自己调试确定,毕竟不同的结构正反也不同。
值得一提的是,P32、P33引脚不是唯一的,只需要将A接入外部中断触发即可,P33则可以换到其他引脚使用。
五,软件消抖
EC11在实际的使用过程中,会存在很多抖动的问题,有时候我们只是转动一格,但是单片机进入了两次中断。如果我们需要更加流畅去操作,即转动一格只进入一次外部中断,这时候需要我们对EC11编码器进行消抖。
消抖方式:硬件消抖、软件消抖。
硬件消抖
一般是采样并联电容的办法,利用电容电压不能突变的性质,对其进行滤波,这里我就不多介绍了,如果感兴趣的话,可以去搜索相关的文章。
软件消抖
一般是使用延时的办法,避开机械抖动的那段时间,从而达到滤波的目的,例如我们的独立按键,就经常使用软件滤波的办法。
消抖思路
①设置定时器中断,定时周期为1ms
②EC11进入一次外部中断,暂时关闭50ms(或者更小,例如20ms),并激活延时变量,使其开始计时。
③计时完成之后,清除中断标志位和延时变量,并重新使能外部中断。
unsigned int ec11_delay;
unsigned char ec11_num;
void Timer0_Init(void) //1毫秒@24.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初始值
TH0 = 0xF8; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1;
EA=1;
}
void INT0_Init()
{
IT0=1; //下降沿触发
IE0=0; //清楚中断标志位
EX0=1; //打开外部中断请求
EA=1; //打开中断总开关
}
void INTO_Routine() interrupt 0
{
if(P33) //逆时针
{
ec11_num--;
}
else //顺时针
{
ec11_num++;
}
EX0=0;//关闭外部中断
ec11_delay=1;//激活延时
}
void Timer0_Routinue() interrupt 1 //1ms
{
if(ec11_delay)
{
if(++ec11_delay>=50) //延时50ms
{
IE0=0; //清楚外部中断标志位
EX0=1; //重新使能外部中断
ec11_delay=0; //退出延时
}
}
}
如果感觉对你有帮助的话,请点个赞吧!
更多推荐
所有评论(0)