1. 算法介绍: 解码程序共处理四种状态,分别是:
a.两条线都是高电平时表示编码器无动作,退出.
b.先检测测的两条线是01,后检测两条线是10时为正转.
c.先检测测的两条线是10,后检测两条线是01时为反转.
d.两条线都是低电平时退出,不处理低电平区.
(两个状态为一个周期,如正转时,先保存旧值01,然后检测新值为10时就为一个成功检测周期. )
使用时请先定义好两个IO口 PINA,PINB,和一个周期数cycle,这两个脚可以是任意两个IO脚,cycle 是指编码器旋转多少格(多少周期)动作一次,一般设置为 1 或 2 .该函数返回三个值,返回0时编码器没有动作,返回1时为正转,返回2时为反转,如果在使用时正反转颠倒,可以交换两个IO口的定义. 不管编码器有无动作该函数都会返回一个值!!!!!!!!!!
//========================================================================================
#include<reg52.h>
typedef unsigned char uchar;
sbit PINA = P2^2; //定义IO
sbit PINB = P2^3;
#define cycle 1 //定义动作周期,编码器旋转多少格有效
#define NULL 0 //定义编码器不动作时的还回值
#define E_RIGHT 0x0e //定义右旋转还回值
#define E_LEFT 0x0f //定义左旋转还回值
uchar WheelNow,WheelOld,RightCount,LeftCount,num;
//========================================================================================
uchar WheelRight()
{
LeftCount=0;
RightCount++;
if (RightCount>=cycle){
RightCount=0;
return(E_RIGHT);
} else return(NULL);
}
//========================================================================================
uchar WheelLeft()
{
RightCount=0;
LeftCount++;
if (LeftCount>=cycle){
LeftCount=0;
return(E_LEFT);
} else return(NULL);
}
//========================================================================================
uchar EncoderProcess()
{
uchar keytmp;
PINA = 1;
PINB = 1;
WheelNow=WheelNow<<1;
if (PINA==1) WheelNow=WheelNow+1; // 读 PINA
WheelNow=WheelNow<<1;
if (PINB==1) WheelNow=WheelNow+1; // 读 PINB
WheelNow=WheelNow & 0x03; // 将 WheelNow 的 2 - 7 位清零,保留 0- 1 两个位的状态.
if (WheelNow==0x00) return(NULL); //当 PINA 和 PINB都为低电平时退出,低电平区不做处理
keytmp=WheelNow;
keytmp ^=WheelOld; // 判断新读的数据同旧数据
if (keytmp==0) return(NULL); // 新读的数据同旧数据一样时退出.
if (WheelOld==0x01 && WheelNow==0x02){ // 是左旋转否
WheelOld=WheelNow;
return(WheelLeft()); //左旋转
}
else if (WheelOld==0x02 && WheelNow==0x01){ // 是右旋转否
WheelOld=WheelNow;
return(WheelRight()); //右旋转
}
WheelOld=WheelNow; // 保存当前值
return(NULL); // 当 PINA 和 PINB 都为高电平时表示编码器没有动作,退出
}
//========================================================================================
void inc()
{
num++;
if (num > 99){
num=0;
}
} // 在此处设置断点看 num 加的变化
//========================================================================================
void dec()
{
num--;
if (num > 99){
num=99;
}
} // 在此处设置断点看 num 减的变化
//========================================================================================
void main()
{
while (1){
switch(EncoderProcess()){
case E_RIGHT: inc(); break;
case E_LEFT: dec(); break;
}
}
}
//========================================================================================
(注:使用定时器每隔1ms读取此函数时,不管编码器转多块也不会丢失num的值)
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
其实我这种方法并可取,需要cpu每隔1ms不断的扫描,导致占用cpu带宽。
用外部中断就比较好
用中断,我也遇到这个问题
一周热门 更多>