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

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条回答
jetli
1楼-- · 2020-01-19 09:21
无衣师伊 发表于 2013-9-24 00:01
我也考虑了很久.用单片机做确实很吃力
有些客户会接上1600线的编码器.单片机根本跟不上.
一开始我用的是:1 ...

记得,流明 的M0  有 正交编码器输入口,专用的
mcu-avr
2楼-- · 2020-01-19 12:37
这里说的编码器就是一键飞梭,并不是脉冲编码器,不会太快的。
ycwjl728
3楼-- · 2020-01-19 18:23
学习之,感谢楼主思路
bosia仔
4楼-- · 2020-01-19 23:14
学习了!!!
机器人天空
5楼-- · 2020-01-20 02:31
 精彩回答 2  元偷偷看……
mcu-avr
6楼-- · 2020-01-20 04:52
楼主的程序到是没有什么逻辑问题,但怎么考虑“防抖”的?如果“防抖”处理的到位也可以抗干扰。
不知道你是怎么处理“防抖”的?

一周热门 更多>