|
发表于 2021-7-4 20:49:47
|
显示全部楼层
本帖最后由 dbxzjq 于 2021-7-4 21:43 编辑
通过楼上的代码改写出支持一定位一脉冲和两定位一脉冲,经过测试,放进1毫秒的定时器中断服务执行,非常好使
分别测量了一个EC11 20格的一定位一脉冲和EC16 30格,两定位一脉冲,都可以完美操作,代码最好不要放主循环,如果主循环
无法保证少于1毫秒扫描一次,扭快就会丢步,放定时器中断,也得必须少于1毫秒中断一次进行扫描
IO均初始化为高电平,准确双向口,或其它的输入口类型,按单片机的IO类型选择,是否要外接上拉电阻
sbit Enc_A = P3^7; //Encoder右旋
sbit Enc_S = P3^6; //Encoder按键
sbit Enc_B = P3^5; //Encoder左旋
unsigned char Enc_Type=0; //Enc_Type=0 一定位一脉冲,=1两定位一脉冲
//函数返回值 0:无动作; 1:正转; -1:反转; 2:只按下按键; 3:按下按键同时正转; -3:按下按键同时反转动;
char Encoder_Scan()
{
char ScanResult = 0; //返回编码器扫描结果,用于分析编码器的动作
// 0:无动作; 1:正转; -1:反转;
// 2:只按下按键; 3:按下按键同时正转 -3:按下按键同时反转动
static unsigned char dir=0; //编码器状态
if(Enc_Type == 0) //一定位一脉冲
{
if(Enc_A == 1 && Enc_B == 1) dir = 0; //一定位一脉冲不动作时都只有一种状态,即只要卡在定位的状态A和B都为高电平
else if(End_A ==0 && Enc_B==1 && dir ==0) dir ='R'; //A和B不相等时证明已经被扭动,通过A和B对应的电平判断出方向,此为第一次扫描
else if(End_A ==1 && Enc_B==0 && dir ==0) dir ='L';
else if(End_A ==0 && Enc_B==0 && dir !=0xff) //当扭到A和B都在低电平状态时执行处理相应的方向,此为第二次扫描
{
if(dir =='L')
{
ScanResult = -1;
dir=0xff;
}else if(dir =='R')
{
ScanResult = 1;
dir=0xff;
}
}
}else if(EC11_Type == 1) //两定位一脉冲
{ //两定位一脉冲的,定位卡,间隔的定位卡位上的A和B电平是有两种电平状态的,一格A和B都为高电平,一格A和B都为低电平
if(Enc_A == 1 && Enc_B == 1) dir = 1; //两定位一脉冲编码的当前定位状态1,A和B同时都为高电平
else if(Enc_A == 0 && Enc_B == 0) dir = 0; //两定位一脉冲编码的的当前定位状态2,A和B同时都为高电平
else if((Enc_A ==0 && Enc_B==1 && dir==1)||(Enc_A ==1 && Enc_B==0 && dir==0)) dir = 'R'; //对应两种定位电平判断方向
else if((Enc_A ==1 && Enc_B==0 && dir==1)||(Enc_A ==0 && Enc_B==1 && dir==0)) dir = 'L'; //对应两种定位电平判断方向
else if(dir != 0xFF ) //由于一格只能半个脉冲变化,不能像一定位一脉冲哪样,两状态扫描才进入处理确定方向
{
if(dir =='L')
{
ScanResult = -1;
dir=0xFF;
}else if(dir =='R')
{
ScanResult = 1;
dir=0xFF;
}
}
}
if(Enc_S == 0) //按键被按下
{
if(ScanResult == 0) ScanResult = 2; //只按下了按键
else if(ScanResult == 1) ScanResult = 3; //按下按键同时正转
else if(ScanResult == -1) ScanResult = -3; //按下按键同时反转
}
return ScanResult;
}
通过扫描得到编码器上的动作返回值,进行下一步的动作分析处理
按键还得应该加入消抖计数,对于按键还可以进一步处理单击,双击,短按,长按等处理 |
|