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

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

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
53条回答
czzhouyun
2020-01-16 16:58
jz701209李 发表于 2013-9-10 19:36
这种机械编码器,能有多快?小白,轻拍

一般工程使用以500脉冲为例,以每秒20圈来说就是10000个脉冲每秒,要分辨方向就必须读两根线,每根线都有10000个脉冲,也就是说如果两根线都是接入中断的那么一次中断周期就是50us,如果是四倍频则是25us进一次中断,如果用指令周期为1us的单片机来说,只要你有足够的技巧处理25us中断一次的数据,那么普通的读编码器就没有问题,关键的问题是很多时候加速或刹车的时候转动速度会超过20圈每秒,表现的现象是重复几次相同位置的数据总在变化,加一或减一,误差在不断累计,或者电路的不稳定,有干扰,停在那数字在不断变化,其实编码器在临界点上不断地颤动,一般工程应用不提倡使用IO口直接读写,而使用CPLD或编码器专用芯片,要不然产生的问题会一直无法解决

一周热门 更多>