正文

【039】两位数码管对直控按键计数2007-05-05 16:25:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wentao/25593.html

分享到:

  • ;**************************************************************************   
  • ; 标题: 两位数码管对直控按键计数(汇编)   
  • ; 作者: wentao     http://blog.liuwentao.net   
  • ;                  http://wentao.programfan.com   
  • ; 日期: 2007.3.2   
  • ; 软件: Keil A51 V8.00    
  • ; 芯片: AT89X51   
  • ; 说明: 实验板实测通过,数码管为8位共阳   
  • ; 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!    
  • ;**************************************************************************   
  •   
  • dis_0 equ 30h        ;dis_0(30单元)存储个位值   
  • dis_1 equ 31h        ;dis_1(31单元)存储十位值   
  • dis_b equ 32h        ;dis_b(32单元)作为位码选通数码管   
  • dis_r equ 33h        ;dis_r(33单元)为切换dis_0和dis_1的偏移量   
  • count equ 34h        ;count(34单元)为计数器   
  • key_v equ 35h        ;key_v(35单元)存储键值   
  • key_t equ 36h        ;key_t(36单元)检测键值时临时存储键值   
  •   
  •           org   0000h  
  •           ajmp  start   
  •           org   000bh           ;定时器0的中断入口地址   
  •           ajmp  time0           ;跳到定时器0的中断服务程序处   
  •           org   0030h  
  • start:    mov   count,#0        ;计数器清0   
  •           mov   p2,#0xff        ;关所有数码管   
  •           mov   dis_b,#0x7f     ;初始选通P2.7口数码管   
  •           mov   dis_r,#0        ;初始化偏移量为0   
  •             
  •           mov   tmod,#00000001b ;定时/计数器0工作于方式1   
  •           mov   th0,#0xfc       ;预置定时常数64536(fc18)   
  •           mov   tl0,#0x18  
  •           setb  ea              ;开总中断   
  •           setb  et0             ;定时/计数器0允许中断   
  •           setb  tr0             ;启动定时/计数器0   
  •              
  • lop:      lcall key_scan        ;调用键扫描子程序   
  •           lcall key_to          ;调用键处理子程序   
  •           ajmp  lop             ;循环   
  •   
  • ;-------------------------------------------------------------------------   
  • key_scan:                       ;键扫描子程序   
  •           mov   a,p1            ;当前键值送入a   
  •           mov   key_t,a         ;存储到临时变量中   
  •           xrl   a,key_v         ;检测键值是否改变   
  •           jz    key_scan        ;未改变则继续扫描   
  •           lcall d_10ms          ;有键按下则延时10ms消抖   
  •           mov   a,p1            ;再次读入键值   
  •           mov   key_t,a         ;键值存储到临时变量中   
  •           xrl   a,key_v         ;检测键值是否改变   
  •           jz    key_scan        ;未改变则继续扫描   
  •           mov   key_v,key_t     ;将最终读到的键值存入key_v   
  •           ret  
  •   
  • key_to:                         ;按键处理子程序   
  •           mov   a,key_v         ;读入键值   
  •           cjne  a,#0xef,next    ;不是P1.4口键值则查下一个   
  •           ajmp  key_1           ;是P1.4口键则转到键处理部分   
  • next:     cjne  a,#0xdf,back    ;也不是P1.5口键值则结束   
  •           ajmp  key_2           ;是P1.5口键则转到键处理部分   
  • back:     ret                   ;结束   
  • key_1:                          ;P1.4口键处理部分   
  •           inc   count           ;计数器加1   
  •           mov   a,count         ;计数器值送入a   
  •           cjne  a,#100,over_1   ;未计到100不处理   
  •           mov   count,#0        ;计到100则清零   
  • over_1:   ret  
  • key_2:                          ;P1.5口键处理部分   
  •           mov   a,count         ;计数器值送入a   
  •           cjne  a,#0,over_2     ;计数值不为0   
  •           mov   count,#99       ;若计数值为0则置为99   
  •           ret  
  • over_2:   dec   count           ;计数值不为0则减1   
  •           ret  
  • ;-------------------------------------------------------------------------   
  •   
  • time0:                       ;定时器0中断服务程序,用于数码管动态显示(1ms)   
  •           mov   dptr,#table  ;段码表首址送入dptr   
  •              
  •           mov   a,count      ;计数器值送入a(被除数)   
  •           mov   b,#10        ;除数10送入b   
  •           div   ab           ;a除以b   
  •           mov   dis_0,b      ;余数b(个位值)送入个位存储单元   
  •           mov   dis_1,a      ;商a(十位值)送入十位存储单元    
  •                              ;以上是将计数值个位十位分开   
  •                              ;以下是将分开的个位十位分别在两个数码管上显示   
  •   
  •           mov   a,#dis_0     ;个位值的地址送入a   
  •           add   a,dis_r      ;基址+偏移量   
  •           mov   r0,a         ;r0为欲显示值的地址   
  •           mov   a,@r0        ;欲显示值送入a   
  •                              ;(dis_t=0时为dis_0值,dis_t=1时为dis_1值)   
  •           movc  a,@a+dptr    ;对应的段码送入a中   
  •           mov   p0,a         ;段码送入P0口   
  •           mov   p2,dis_b     ;位码送入P2口   
  •              
  •           xrl   dis_r,#0x01  ;异或01使偏移量在0和1间切换   
  •           xrl   dis_b,#0xc0  ;异或c0使位码在7f(P2.7)和bf(P2.6)间循环   
  •   
  •           mov   th0,#0xfc    ;重置定时常数64536(fc18)   
  •           mov   tl0,#0x18  
  •           reti  
  •   
  • d_10ms:   mov   r5,#20        ;1+(1+2*255)*20+2*20=10.261ms@12M   
  • temp:     mov   r6,#255       ;1+2*255   
  •           djnz  r6,$   
  •           djnz  r5,temp   
  •           ret  
  •   
  • table:    db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90  ;段码表   
  •            ;   0    1    2    3    4    5    6    7    8    9    对应内容   
  •   
  • end 


  • /**************************************************************************  
  • * 标题: 两位数码管对直控按键计数(C51)  
  • * 作者: wentao     http://blog.liuwentao.net  
  •                    http://wentao.programfan.com  
  • * 日期: 2007.3.2  
  • * 软件: Keil C51 V8.02  
  • * 芯片: AT89X51  
  • * 说明: 实验板实测通过,数码管为8位共阳  
  • * 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!   
  • **************************************************************************/  
  •   
  • #include <reg51.h>   
  • #define uchar unsigned char   
  •   
  • void delay_ms(uchar ms);  // 延时毫秒@12M,ms最大值255   
  • void key_scan();          // 按键扫描   
  • void key_to(uchar key_v); // 按键处理   
  •   
  • uchar code dis_code[10] = {0xc0,0xf9,0xa4,0xb0,0x99,  //段码表   
  •                           // 0    1    2    3    4      对应内容   
  •                            0x92,0x82,0xf8,0x80,0x90};   
  •                           // 5    6    7    8    9   
  •   
  • uchar data dis[2];        // dis[0]为个位值,dis[1]为十位值   
  • uchar data dis_b;         // 选通数码管的位码   
  • uchar data dis_r;         // 个位十位段码切换的偏移量   
  • uchar data count;         // 计数器   
  • uchar data key_v;         // 存储键值   
  • uchar data key_t;         // 扫描按键时临时存储键值   
  •   
  • void main()   
  • {   
  •     count = 0;           // 计数器清零   
  •     P2 = 0xff;           // 关所有数码管   
  •     dis_b = 0x7f;        // 初始选通P2.7口数码管   
  •     dis_r = 0;           // 初始化偏移量为0   
  •        
  •     TMOD = 0x01;         // 定时/计数器0工作于方式1   
  •     TH0 = 0xfc;          // 装载定时常数64536(fc18)   
  •     TL0 = 0x18;   
  •     EA = 1;              // 开总中断   
  •     ET0 = 1;             // 定时/计数器0允许中断   
  •     TR0 = 1;             // 启动定时/计数器0   
  •     while(1)             // 执行主程序,等待中断   
  •     {   
  •         key_scan();     // 扫描按键   
  •         key_to(key_v);  // 处理按键   
  •     }   
  • }   
  • void key_scan()                // 按键扫描   
  • {   
  •     while(1)   
  •     {   
  •         key_t = P1;            // 读入键值   
  •         if(key_t != key_v)     // 若键值改变   
  •         {   
  •             delay_ms(10);      // 延时10ms消抖   
  •             key_t = P1;        // 再次读入键值   
  •             if(key_t != key_v) // 确定有键按下   
  •             {   
  •                 key_v = key_t; // 保存键值   
  •                 break;         // 跳出循环结束扫描   
  •             }   
  •         }   
  •     }   
  • }   
  • void key_to(uchar key_v)       // 按键处理   
  • {   
  •     if(key_v == 0xef)          // 若为P1.4口按键   
  •     {   
  •         count++;               // 计数器加1   
  •         if(count == 100)       // 计到100后清零   
  •             count = 0;   
  •     }   
  •     else  
  •     {   
  •         if(key_v == 0xdf)      // 若为P1.5口按键   
  •         {   
  •             if(count == 0)     // 若计数器为0则置为99   
  •                 count = 99;   
  •             else               // 不为0则减1   
  •                 count--;   
  •         }   
  •     }   
  • }   
  • void time0(voidinterrupt 1   // T/C0中断服务程序(延时1ms数码管动态显示)   
  • {   
  •     dis[1] = count / 10;       // 计数器十位分离出来赋绐dis[1]   
  •     dis[0] = count % 10;       // 计数器个位分离出来赋绐dis[0]   
  •   
  •     P0 = dis_code[dis[dis_r]]; // 段码送P0口,dis_r=0时为个位dis[0]的值   
  •                                //            dis_r=1时为十位dis[1]的值   
  •     P2 = dis_b;                // 位码送P2口   
  •   
  •     dis_r ^= 0x01;             // 异或01使偏移量在0和1间切换   
  •     dis_b ^= 0xc0;             // 异或c0使位码在7f(P2.7)和bf(P2.6)间循环   
  •   
  •     TH0 = 0xfc;                // 重置定时常数   
  •     TL0 = 0x18;   
  •   
  • }   
  • void delay_ms(uchar ms)       // 延时毫秒@12M,ms最大值255   
  • {   
  •     uchar i;   
  •     while(ms--)   
  •         for(i = 0; i < 124; i++);   
  • }


  • 阅读(6860) | 评论(6)


    版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

    评论

    loading...
    您需要登录后才能评论,请 登录 或者 注册