机械式旋转编码器解码程序

2020-01-15 19:20发布

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的值)

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
52条回答
无级电工
1楼-- · 2020-01-16 00:07
收藏了。不过我还是倾向用中断来做。
机器人天空
2楼-- · 2020-01-16 01:16
无级电工 发表于 2013-9-10 15:10
收藏了。不过我还是倾向用中断来做。

当编码器旋转的太快时用中断会不会漏检
qiaoqiang
3楼-- · 2020-01-16 04:22
就怕你发送太快,接收不过来阿
xiaobendan001
4楼-- · 2020-01-16 07:04
机器人天空 发表于 2013-9-10 16:00
当编码器旋转的太快时用中断会不会漏检

不管中断还是扫描,信号太快都会漏的。
实际上中断能适应更高的频率
我一般这样,一个信号用中断,一个用IO,中断里面检测IO状态,高电平加一,低电平减一,但是抗干扰始终是问题。
jetli
5楼-- · 2020-01-16 08:24
 精彩回答 2  元偷偷看……
jz701209李
6楼-- · 2020-01-16 12:32
这种机械编码器,能有多快?小白,轻拍

一周热门 更多>