注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
chich的个人空间 https://home.eeworld.com.cn/space-uid-88198.html [收藏] [复制] [分享] [RSS]
日志

旋转编码器程序

已有 6334 次阅读2010-9-26 22:31

最近用到旋转编码器,在网上找了一大堆资料,发现这篇好文章。收藏到自己的空间待用。
 
[ME850扩展应用]旋转编码器计数程序(飞梭旋钮功能)-数码管显示
/*******************************************************************
*                                                                  *
* ME850单片机开发实验仪演示程序 -  旋转编码器计数程序              *
*                                                                  *
* 3位数码管显示                                                    *
*                                                                  *
* MCU: AT89S52   晶振:11.0592MHz                                  *
*                                                                  *
* 版本:V1.1 (2009/04/29)                                          *
* 作者:gguoqing  (Email: gguoqing@willar.com)                     *
* 网站:www.sofi-tech.com (硕飞科技)                               *
*       www.mcusj.com (伟纳单片机世界)                             *
* 邮箱:sofitech@tom.com                                           *
*                                                                  *
*【版权】Copyright(C) 深圳硕飞科技有限公司  All Rights Reserved    *
*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!        *
*                                                                  *
********************************************************************
*                                                                  *
*  功能简述: (飞梭旋钮功能)                                       *
*  当旋钮顺时针旋转时,计数值增加。达到最大值255后,不再响应。     *
*  当逆钮顺时针旋转时,计数值减小。达到最小值0后,不再响应。       *
*  当按下旋钮时,将计数值清零(归位)。                            *
*                                                                  *
*******************************************************************/
#include <reg52.h>
sbit     PINA    = P1^0;
sbit     PINB    = P1^1;
sbit     PIND    = P1^2;
unsigned char  display[3];
unsigned char  code  LEDData[ ] =
{
   0xC0,0xF9,0xA4,0xB0,0x99,0x92,
   0x82,0xF8,0x80,0x90,0xff
};
char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节
unsigned char  counter = 0;     //编码器脉冲计数
unsigned char  n,shift;
/**********************************************************
ms延时子函数
**********************************************************/
void delayms(unsigned int ms)
{
  unsigned char k;
  while (ms--)
  {
    for (k = 0; k < 114; k++)
      ;
  }
}
/**********************************************************
扫描编码器子函数
在编码器引脚A为低电平期间:
编码器引脚B从0到1为正转,编码器引脚B从1到0为反转。
**********************************************************/
void scan_encoder(void)
{
   static  bit  Curr_encoder_b;  //定义一个变量来储存当前B信号
   static  bit  Last_encoder_b;  //定义一个变量来储存上次B脚信号
   static  bit  updata= 0;
   if( PINA && PINB)           //编码器无转动退出
   {
     updata = 0;
     return;
   }
   Last_encoder_b = PINB;       //记录B信号
   while(!PINA)                //等待A由低变高
   {
     Curr_encoder_b = PINB;     //记录等待期间的B信号(指当前B信号)
     updata = 1;
   }
   if(updata)
   {
   updata = 0 ;
     if( (Last_encoder_b == 0)&&(Curr_encoder_b== 1) ) //B从0到1为正转
     {
   if(counter == 255)
       return;
       counter++;          //正转计数加
     }
     else if( (Last_encoder_b == 1)&&(Curr_encoder_b == 0) ) //B从1到0为反转
     {
       if(counter == 0)
       return;
       counter--;         //反转计数减
     }
   }
}
/**********************************************************
主函数
**********************************************************/
void  main(void)
{
   P0 = 0xff;
   P1 = 0xff;
   P2 = 0xff;
   T2CON = 0x00;               //设置T2CON寄存器        
   TH2 = 0xfc;                 //1ms定时
   TL2 = 0x66;
   ET2 = 1;                    //启用Timer2中断
   EA = 1;                     //总中断允许
   TR2 = 1;                    //启动定时器2
   counter = 0;                //计数单元清零
   while(1)
   {
   scan_encoder();
     if(! PIND)                //当按下旋钮时
     {
       counter = 0;            //计数单元清零(归位)
       delayms(10);
     }
   }
}
/*********************************************************
Timer2中断函数
**********************************************************/
void  timer2() interrupt 5
{
   TR2 = 0;
   TF2 = 0;                         //手工清中断标志 
   TH2 = 0xfc;                      //1ms定时常数
   TL2 = 0x66;
   if(n >= 3)                       //3位数码管显示
   {
     n = 0;
     shift = 0xfe;                  //送位码初值
     P2 = 0xff;                     //关闭显示
   }
   else
   {
     display[0] = counter%10;       //个位数据
     display[1] = (counter%100)/10; //十位数据
     display[2] = counter/100;      //百位数据
    
     if(display[2] == 0)
     {
       display[2] = 0x0a;           //百位为0,不显示
       if(display[1] == 0)
       display[1]  =0x0a;           //十位为0,不显示
}
     P0 = LEDData[display[n++]];    //送段码
     P2 = shift;                    //送位码
     shift = (shift<<1)|0x01;       //调整位码
   }
   TR2 = 1;
}
/*********************************************************/
 
 
 
 
 
;********************************************************************
;*                                                                  *
;* ME850单片机开发实验仪演示程序 -   旋转编码器计数程序             *
;*                                                                  *
;* 3位数码管显示                                                    *
;*                                                                  *
;* MCU: AT89S52   晶振:11.0592MHz                                  *
;*                                                                  *
;* 版本:V1.1 (2009/04/29)                                          *
;* 作者:gguoqing  (Email: gguoqing@willar.com)                     *
;* 网站:www.sofi-tech.com (硕飞科技)                               *
;*       www.mcusj.com (伟纳单片机世界)                             *
;* 邮箱:sofitech@tom.com                                           *
;*                                                                  *
;*【版权】Copyright(C) 深圳硕飞科技有限公司  All Rights Reserved    *
;*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!        *
;*                                                                  *
;********************************************************************
;*                                                                  *
;*  功能简述: (飞梭旋钮功能)                                       *
;*  当旋钮顺时针旋转时,计数值增加。达到最大值255后,不再响应。     *
;*  当逆钮顺时针旋转时,计数值减小。达到最小值0后,不再响应。       *
;*  当按下旋钮时,将计数值清零(归位)。                            *
;*                                                                  *
;********************************************************************
--------------------------------------------------------------------------------
以下为回复后可浏览的内容:
       $ INCLUDE(TIMER2.INC)
        PINA     BIT  P1.0
        PINB     BIT  P1.1
        PIND     BIT  P1.2
        LAST_B   BIT  20H.0
        CURR_B   BIT  20H.1
        UPDATA   BIT  20H.2
        DISPLAY  EQU  40H
        COUNT    EQU  45H
;**********************************************************
        ORG  0000H
        AJMP  MAIN
        ORG  002BH
        AJMP  TIMER2
        ORG  0050H
;**********************************************************
; 主程序
;**********************************************************
MAIN:
        MOV  SP,#60H           ;设置堆栈指针
        MOV  P0,#0FFH          ;端口初始化
        MOV  P2,#0FFH
        MOV  P1,#0FFH
        MOV  COUNT,#00H        ;清计数单元
        MOV  R0,#DISPLAY       ;获得显示单元首地址
        MOV  R1,#0FEH          ;位码初值     
        MOV  T2CON,#00H        ;设置T2CON寄存器
        MOV  TH2,#0FCH         ;1ms定时常数
        MOV  TL2,#66H
        SETB  ET2              ;允许Timer2中断
        SETB  EA               ;允许总中断
        SETB  TR2
LOOP:
        ACALL  ENCODER_SCAN
        JB  PIND,LOOP          ;判断轴向开关是否按下
        MOV  COUNT,#00H        ;清计数单元(归位)
        AJMP   LOOP
        RET
;**********************************************************
; 编码器扫描子程序
; 在编码器引脚A为低电平期间:
; 编码器引脚B从0变到1为正转,编码器引脚B从1变到0为反转。
;**********************************************************
ENCODER_SCAN:
        MOV  P1,#0FFH
        NOP
        NOP
        MOV  A,P1
        ANL  A,#03H
        CJNE  A,#03H,SCAN1
        AJMP  SCAN_END         ;旋钮没有旋转退出
SCAN1:
        JB  PINB,SCAN1A        ;记录B脚电平
        CLR  LAST_B
        AJMP  SCAN2
SCAN1A:
        SETB  LAST_B
SCAN2: 
        JB  PINA,SCAN3
        SETB  UPDATA           ;当旋钮旋转时,A脚有低电平产生
        JB  PINB,SCAN2A        ;在A为低电平期间,循环记录B脚电平
        CLR  CURR_B
        AJMP  SCAN2
SCAN2A:
        SETB  CURR_B
        AJMP  SCAN2
SCAN3:
        JNB  UPDATA,SCAN_END   ;旋钮没有旋转(没有新数据产生)退出
        JNB  CURR_B,SCAN5      ;
        JB  LAST_B,SCAN_END
        MOV  A,COUNT
        CJNE A,#0FFH,SCAN4     ;判断是否达到最大值
        AJMP  SCAN_END
SCAN4:
        INC  COUNT             ;顺时针旋转,计数值加1
        AJMP  SCAN_END
SCAN5:
        JNB  LAST_B,SCAN_END
        MOV  A,COUNT
        CJNE A,#00H,SCAN6      ;判断是否达到最小值
        AJMP  SCAN_END
SCAN6:
        DEC  COUNT             ;逆时针旋转计数值减1
SCAN_END:
        CLR  UPDATA            ;清更新数据标志
        RET
;**********************************************************
; Timer2 中断服务子程序
;**********************************************************
TIMER2:
        CLR  TR2
        PUSH  ACC
        PUSH  B
        CLR  TF2               ;清中断标志
        MOV  TH2,#0F8H         ;2ms定时常数
        MOV  TL2,#0CCH
        MOV  A,R1
        JB ACC.3,T2_1          ;判3位数码管是否显示完?
        MOV  R0,#DISPLAY       ;获得显示单元首地址
        MOV  R1,#0FEH          ;位码初值
        MOV  P2,#0FFH          ;关闭显示
        AJMP  T2_END
T2_1:
        MOV A,COUNT            ;转换计数值数据
        MOV B,#100
        DIV AB
        MOV DISPLAY+2,A        ;百位数据
        XCH  A,B               ;数据交换
        MOV  B,#10
        DIV AB
        MOV  DISPLAY+1,A       ;十位数据
        MOV  DISPLAY,B         ;个位数据
        MOV  A,DISPLAY+2       ;百位数据
        CJNE A,#00H,T2_2
        MOV  DISPLAY+2,#0AH    ;百位数据为0,不显示
        MOV  A,DISPLAY+1       ;十位数据
        CJNE A,#00H,T2_2
        MOV  DISPLAY+1,#0AH    ;十位数据为0,不显示
T2_2:
        MOV  A,@R0             ;取显示数据
        MOV  DPTR,#TABLE       ;获得表头
        MOVC A,@A+DPTR         ;查表获得段码显示数据
        MOV  P0,A              ;送段码
        MOV  P2,R1             ;送位码
        MOV  A,R1              ;准备下一位显示的位码
        RL A
        MOV  R1,A             
        INC  R0                ;取下一个显示单元地址
T2_END:
        POP  B
        POP  ACC
        SETB  TR2
        RETI
;**********************************************************
TABLE:
      DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
      DB 0FFH  ; '熄灭'
;**********************************************************
        END         ;结束
;**********************************************************
发表评论 评论 (1 个评论)
回复 jjkwz 2010-9-26 23:45
学知识了~谢谢了啊,回帖是美德,嘿嘿~

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章