正文

【043】秒表-六位数码管有效显示2007-05-05 16:30:00

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

分享到:

  • ;**************************************************************************   
  • ; 标题: 秒表-六位数码管有效显示(汇编)   
  • ; 作者: wentao     http://blog.liuwentao.net   
  • ;                  http://wentao.programfan.com   
  • ; 日期: 2007.3.2   
  • ; 软件: Keil A51 V8.00    
  • ; 芯片: AT89X51   
  • ; 说明: 实验板实测通过,数码管为8位共阳   
  • ; 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!    
  • ;**************************************************************************   
  •   
  • dot_l  equ  30h        ;30单元存储百分之一秒值   
  • dot_h  equ  31h        ;31单元存储十分之一秒值   
  • bar_2  equ  32h        ;32单元存储"-"段码的偏移量   
  • sec_l  equ  33h        ;33单元存储秒个位值   
  • sec_h  equ  34h        ;34单元存储秒十位值   
  • bar_5  equ  35h        ;35单元存储"-"段码的偏移量   
  • min_l  equ  36h        ;36单元存储分个位值   
  • min_h  equ  37h        ;37单元存储分十位值   
  •   
  • dot    equ  38h        ;38单元为百分之一秒计数器(0.00s-0.99s)   
  • sec    equ  39h        ;39单元为秒计数器(00s-59s)   
  • min    equ  40h        ;40单元为分计数器(00m-99m)   
  •   
  • dis_b  equ  41h        ;dis_b(41单元)作为位码选通数码管   
  • dis_r  equ  42h        ;dis_r(42单元)为取段码时的偏移量   
  •   
  • key_t  equ  43h        ;43单元为键按下的次数标记   
  •   
  • K      bit  p1.4       ;K键与P1.4相连   
  •   
  •           org   0000h  
  •           ajmp  start   
  •           org   000bh          ;定时器0的中断入口地址   
  •           ajmp  time0          ;跳到定时器0的中断服务程序处   
  •           org   001bh          ;定时器1的中断入口地址   
  •           ajmp  time1          ;跳到定时器1的中断服务程序处   
  •           org   0030h  
  • start:       
  •           mov   p2,#0xff       ;关所有数码管   
  •           mov   p1,#0xff       ;p1为准双向口,作输入时先写1   
  •              
  •           mov   bar_2,#10      ;'-'段码偏移量为10   
  •           mov   bar_5,#10      ;'-'段码偏移量为10   
  •           mov   dis_b,#0x7f    ;初始选通P2.7口数码管   
  •           mov   dis_r,#0       ;初始化偏移量为0   
  •           mov   dot,#0         ;百分之一秒计数器清零   
  •           mov   sec,#0         ;秒计数清零   
  •           mov   min,#0         ;分计数清零   
  •           mov   key_t,#0       ;键按下次数清零   
  •              
  •           mov  tmod,#00010001b ;定时/计数器0、1工作于方式1   
  •           mov  th0,#0xd8       ;预置定时常数55536(d8f0),产生10ms时基信号   
  •           mov  tl0,#0xf0  
  •           mov  th1,#0xfc       ;预置定时常数64536(fc18),产生1ms间隔用于动态显示   
  •           mov  tl1,#0x18  
  •              
  •           setb ea              ;开总中断   
  •           setb et0             ;定时/计数器0允许中断   
  •           setb et1             ;定时/计数器1允许中断   
  •           clr  tr0             ;关定时/计数器0   
  •           setb tr1             ;开定时/计数器1   
  •              
  • lop:  
  •           jb    K,lop          ;键(P1.4)未按下则返回   
  •           lcall d_10ms         ;延时10ms消抖   
  •           jb    K,lop          ;是抖动则返回重新扫描   
  •           jnb   K,$            ;等待键松开   
  •           lcall key_to         ;调用键处理部分   
  •           ajmp  lop            ;循环显示   
  •   
  • key_to:                        ;键处理子程序   
  •           inc   key_t          ;键按下次数加1   
  •           mov   a,key_t        ;按下次数送入a   
  •           cjne  a,#1,key_2     ;不是1次继续检测是否是第2次   
  •           setb  tr0            ;第1次按下启动定时器0   
  •           ret  
  • key_2:    cjne  a,#2,key_3     ;也不是2次继续检测是否是第3次   
  •           clr   tr0            ;第2次按下关闭定时器0   
  •           ret  
  • key_3:    cjne  a,#3,back      ;也不为3则结束   
  •           mov   dot,#0         ;第3次按下将三个计数器清零   
  •           mov   sec,#0  
  •           mov   min,#0  
  •           mov   key_t,#0       ;按键次数清零   
  • back:     ret  
  • ;--------------------------------------------------------------------------------   
  • time0:                        ;定时器0中断服务程序   
  •          push  psw            ;保护现场   
  •          push  acc  
  •             
  •          inc   dot            ;百分之一秒计数器加1   
  •          mov   a,dot          ;计数器值送入a   
  •          cjne  a,#100,over    ;未计到100则返回继续计数   
  •          mov   dot,#0         ;计到100后清零   
  •          inc   sec            ;秒计数器加1(进位10ms*100=1s)   
  •          mov   a,sec          ;秒计数值送入a   
  •          cjne  a,#60,over     ;未计到60则返回继续计数   
  •          mov   sec,#0         ;计到60后秒计数器清零   
  •          inc   min            ;分计数器加1(进位60s=1m)   
  •          mov   a,min          ;分计数值送入a   
  •          cjne  a,#100,over    ;未计到100则返回继续计数   
  •          mov   min,#0         ;计到100后分计数器清零,重新计时   
  •             
  • over:    mov   th0,#0xd8      ;重置定时常数   
  •          mov   tl0,#0xf0  
  •          pop   acc            ;恢复现场   
  •          pop   psw  
  •          reti                 ;中断返回   
  • ;--------------------------------------------------------------------------------   
  • time1:                     ;定时器1中断服务程序   
  •          push  psw         ;保护现场   
  •          push  acc  
  •          push  b  
  •                            ;以下是百分之一秒计数器值个位十位分开   
  •          mov   a,dot       ;百分之一秒计数器值送入a(被除数)   
  •          mov   b,#10       ;除数10送入b   
  •          div   ab          ;a除以b   
  •          mov   dot_l,b     ;余数b(百分之一秒值)送入百分之一秒存储单元   
  •          mov   dot_h,a     ;商a(十分之一秒值)送入十分之一秒存储单元    
  •                            ;以下是秒计数器值个位十位分开   
  •          mov   a,sec       ;秒计数器值送入a(被除数)   
  •          mov   b,#10       ;除数10送入b   
  •          div   ab  
  •          mov   sec_l,b     ;余数b(秒个位值)送入秒个位存储单元   
  •          mov   sec_h,a     ;商a(秒十位值)送入秒十位存储单元   
  •                            ;以下是分计数器值个位十位分开   
  •          mov   a,min       ;分计数器值送入a(被除数)   
  •          mov   b,#10       ;除数10送入b   
  •          div   ab  
  •          mov   min_l,b     ;余数b(分个位值)送入分个位存储单元   
  •          mov   min_h,a     ;商a(分十位值)送入分十位存储单元   
  •             
  •          mov   dptr,#table ;数码管段码表首址送入dptr   
  •             
  •          mov   a,#dot_l    ;取百分之一秒值的地址   
  •          add   a,dis_r     ;基址+偏移量   
  •          mov   r0,a        ;R0为欲显示值的地址   
  •          mov   a,@r0       ;取欲显示值送入a   
  •                            ; dis_r  :   0     1     2     3     4     5     6     7   
  •                            ;对应单元: dot_l dot_h bar_2 sec_l sec_h bar_5 min_l min_h   
  •          movc  a,@a+dptr   ;取对应值的段码   
  •          mov   p0,a        ;段码送入P0口   
  •          mov   p2,dis_b    ;位码送入P2口   
  •             
  •          inc   dis_r       ;偏移量加1,下次中断时显示下个数   
  •          anl   dis_r,#0x07 ;dis_r增到8时自动清0(使之在0到7间循环)   
  •             
  •          mov   a,dis_b     ;位码循环右移,下次中断时选通下个数码管   
  •          rr    a  
  •          mov   dis_b,a  
  •             
  •          mov   th1,#0xfc   ;重置定时常数   
  •          mov   tl1,#0x18  
  •             
  •          pop   b  
  •          pop   acc         ;恢复现场   
  •          pop   psw  
  •          reti  
  •   
  • d_10ms:  mov   r5,#20      ;1+(1+2*255)*20+2*20=10.261ms@12M   
  • temp1:   mov   r6,#255     ;1+2*255   
  •          djnz  r6,$   
  •          djnz  r5,temp1   
  •          ret  
  •               
  • table:  db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf ;段码表   
  •          ;   0    1    2    3    4    5    6    7    8    9    -  对应内容   
  •   
  • end 


  • /**************************************************************************  
  • * 标题: 秒表-六位数码管有效显示(C51)  
  • * 作者: wentao     http://blog.liuwentao.net  
  •                    http://wentao.programfan.com  
  • * 日期: 2007.3.3  
  • * 软件: Keil C51 V8.02  
  • * 芯片: AT89X51  
  • * 说明: 实验板实测通过,数码管为8位共阳  
  • * 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!   
  • **************************************************************************/  
  •   
  • #include <reg51.h>   
  • #include <intrins.h>   
  • #define uchar unsigned char   
  •   
  • void delay_ms(uchar ms);  // 延时毫秒@12M,ms最大值255   
  • void key_scan();          // 按键扫描   
  • void key_to();            // 按键处理   
  •   
  • uchar code dis_code[11] = {0xc0,0xf9,0xa4,0xb0,0x99,       //段码表   
  •                           // 0    1    2    3    4         对应内容   
  •                            0x92,0x82,0xf8,0x80,0x90,0xbf};   
  •                           // 5    6    7    8    9    -   
  •   
  • uchar data dis[8];       // dis[0]为百分之一秒值,dis[1]为十分之一秒值   
  •                          // dis[2],dis[5]为'-'段码的偏移量   
  •                          // dis[3]为秒个位值,dis[4]为秒十位值   
  •                          // dis[6]为分个位值,dis[7]为分十位值   
  •   
  • uchar data dot = 0;      // 百分之一秒计数器(0.00s-0.99s)   
  • uchar data sec = 0;      // 秒计数器(00s-59s)   
  • uchar data min = 0;      // 分计数器(00m-99m)   
  •   
  • uchar data dis_b;        // dis_b为位码选通数码管   
  • uchar data dis_r;        // dis_r为取段码时的偏移量   
  •   
  • uchar data key_t = 0;    // 按键次数,初始为0   
  •   
  • sbit  K = P1^4;          // K键与P1.4相连   
  •   
  • void main()   
  • {   
  •     P2 = 0xff;           // 关所有数码管   
  •     P1 = 0xff;           // p1为准双向口,作输入时先写1   
  •     dis[2] = 10;         // '-'在段码表中偏移量为10   
  •     dis[5] = 10;         // '-'在段码表中偏移量为10   
  •     dis_b = 0x7f;        // 初始选通P2.7口数码管   
  •     dis_r = 0;           // 初始化偏移量为0   
  •        
  •     TMOD = 0x11;         // 定时/计数器0,1工作于方式1   
  •     TH0 = 0xd8;          // 预置定时常数55536(d8f0),产生10ms时基信号   
  •     TL0 = 0xf0;   
  •     TH1 = 0xfc;          // 预置定时常数64536(fc18),产生1ms间隔用于动态显示   
  •     TH1 = 0x18;   
  •     EA = 1;              // 开总中断   
  •     ET0 = 1;             // 定时/计数器0允许中断   
  •     ET1 = 1;             // 定时/计数器1允许中断   
  •     TR0 = 0;             // 关闭定时/计数器0   
  •     TR1 = 1;             // 启动定时/计数器1   
  •     while(1)   
  •     {   
  •         if(K != 1)             // 有键按下   
  •         {   
  •             delay_ms(10);      // 延时10ms去抖   
  •             if(K != 1)         // 确定是有键按下   
  •             {   
  •                 while(K != 1); // 等待键松开   
  •                 key_to();      // 按键处理   
  •             }   
  •         }   
  •     }   
  • }   
  • void key_to()                  // 按键处理子程序   
  • {   
  •     key_t++;                   // 按键次数加1   
  •     if(key_t == 1)             // 第一次按下   
  •         TR0 = 1;               // 启动定时器0   
  •     else  
  •     {   
  •         if(key_t == 2)         // 第二次按下   
  •             TR0 = 0;           // 关闭定时器0   
  •         else  
  •         {   
  •             if(key_t == 3)     // 第三次按下   
  •             {   
  •                 dot = 0;       // 三个计数器清零   
  •                 sec = 0;   
  •                 min = 0;   
  •                 key_t = 0;     // 按键次数清零   
  •             }   
  •         }   
  •     }   
  •   
  • }   
  • void tiem0(voidinterrupt 1   // T/C0中断服务程序(产生10ms时基信号)   
  • {   
  •     dot++;                     // 百分之一秒计数器加1   
  •     if(dot == 100)             // 计数值到100   
  •     {   
  •         dot = 0;               // 清零   
  •         sec++;                 // 秒计数器加1(进位10ms*100=1s)   
  •         if(sec == 60)          // 秒计数值到60   
  •         {   
  •             sec = 0;           // 秒计数器清零   
  •             min++;             // 分计数器加1(进位60s=1m)   
  •             if(min == 100)     // 分计数到100   
  •                 min = 0;       // 分计数器清零   
  •         }   
  •     }   
  •     TH0 = 0xd8;                // 重置定时常数   
  •     TL0 = 0xf0;   
  • }   
  • void time1(voidinterrupt 3   // T/C1中断服务程序(延时1ms数码管动态显示)   
  • {   
  •     dis[0] = dot % 10;         // 百分之一秒计数器个位分离出来赋绐dis[0]   
  •     dis[1] = dot / 10;         // 百分之一秒计数器十位分离出来赋绐dis[1]   
  •     dis[3] = sec % 10;         // 秒计数器个位赋绐dis[3]   
  •     dis[4] = sec / 10;         // 秒计数器十位赋绐dis[4]   
  •     dis[6] = min % 10;         // 分计数器个位赋绐dis[6]   
  •     dis[7] = min / 10;         // 分计数器十位赋绐dis[7]   
  •   
  •     P0 = dis_code[dis[dis_r]]; // 段码送P0口(dis[0]...dis[7])   
  •     P2 = dis_b;                // 位码送P2口   
  •   
  •     dis_r++;                   // 偏移量加1,下次中断时显示下个数   
  •     dis_r &= 0x07;             // dis_r增到8时自动清0(使之在0到7间循环)   
  •        
  •     dis_b = _cror_(dis_b,1);   // 位码循环右移,下次中断时选通下个数码管   
  •   
  •     TH1 = 0xfc;                // 重置定时常数   
  •     TL1 = 0x18;   
  •   
  • }   
  • void delay_ms(uchar ms)       // 延时毫秒@12M,ms最大值255   
  • {   
  •     uchar i;   
  •     while(ms--)   
  •         for(i = 0; i < 124; i++);   
  • }


  • 阅读(7096) | 评论(1)


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

    评论

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