赞
踩
在网上下载过很多种编码器解码程序,使用后感觉都不够稳定,特别是旋转速度稍快时,经常会出现错误解码。为此,经过分析编码器输出波形特点,结合其它解码程序的优点,编写如下代码,不用中断,也可以不用定时器。经过一段时间使用,效果很好,不论旋转速度快慢,都不会出现错误解码,比较稳定。
此程序在STC15W408AS单片机上调试通过,理论上其它C51单片机也可以;函数可以在循环中调用,也可在定时器中调用(定时器中调用时间间隔最好小于1毫秒,否则旋转快了会丢码);支持一定位一脉冲、两定位一脉冲的编码器解码,函数中可设置编码器类型;PINA和PINB是编码器两个引脚连接的IO口。编码器静止时函数返回0, 正转(向右转)返回单字符'R',反转(向左转)返回单字符'L',也可根据需要自行更改。
调用示例:
#include
unsigned char Encoder(void);
sbit PINA=P1^1;
sbit PINB=P1^2;
void main(void)
{
unsigned char enc,x=0,y=0;
while(1)
{
enc=Encoder(); //扫描编码器,取得返回值
if(enc=='R')x++; //正转x累加
if(enc=='L')y++; //反转y累加
//以下为显示或数据处理
}
}
/************************************************************************************************
函数名称:Encoder
函数功能:编码器旋转的扫描及处理
入口参数:无
出口参数:char型 0-无旋转 'R'-正转(向右转) 'L'-反转(向左转)
************************************************************************************************/
unsigned char Encoder(void)
{
static bit Enc0=0,Enc1=0;
static unsigned char EncOld,EncX=0;
unsigned char EncNow;
bit EncType=0; //设置编码器类型: 0为一定位一脉冲,1为两定位一脉冲
PINA=1; //PINA置高电平
PINB=1; //PINB置高电平
if(Enc0==0)EncOld=(PINA?0x02:0x00)+(PINB?0x01:0x00),Enc0=1; //记住初次调用时编码器的状态
EncNow=(PINA?0x02:0x00)+(PINB?0x01:0x00); //根据两个IO当前状态组合成16进制的0x00|0x01|0x02|0x03
if(EncNow==EncOld)return(0); //如果新数据和原来的数据一样(没有转动)就直接返回0
if(EncOld==0x00&&EncNow==0x02||EncOld==0x03&&EncNow==0x01)EncX=EncNow; //00-10|11-01
if(EncOld==0x00&&EncX==0x02&&EncNow==0x03||EncOld==0x03&&EncX==0x01&&EncNow==0x00)//00-10-11|11-01-00右转
{
EncOld=EncNow,EncX=0;
if(EncType==1)return('R'); //两定位一脉冲
else //一定位一脉冲
{
if(Enc1==0)Enc1=1;
else
{
//Delayms(60); //延时降低旋转灵敏度(不能用在定时器中)
Enc1=0;
return('R');
}
}
}
if(EncOld==0x00&&EncNow==0x01||EncOld==0x03&&EncNow==0x02)EncX=EncNow; //00-01|11-10
if(EncOld==0x00&&EncX==0x01&&EncNow==0x03||EncOld==0x03&&EncX==0x02&&EncNow==0x00)//00-01-11|11-10-00左转
{
EncOld=EncNow,EncX=0;
if(EncType==1)return('L'); //两定位一脉冲
else //一定位一脉冲
{
if(Enc1==0)Enc1=1;
else
{
//Delayms(60); //延时降低旋转灵敏度(不能用在定时器中)
Enc1=0;
return('L');
}
}
}
return(0); //没有正确解码返回0
}
评分
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。