正文

【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(void) interrupt 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(void) interrupt 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++);    }

阅读(11882) | 评论(1)


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

评论

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