美文网首页程序员
单片机实现秒表计时

单片机实现秒表计时

作者: ERROR505 | 来源:发表于2019-11-10 13:35 被阅读0次

    要求:

    用stc89c51,数码管,锁存器实现秒表功能

    实验仿真图:

    1.png

    加入两个锁存器使单片机能够分时进行位选和段选,这样做的目的是为了节省单片机的端口数量。P0口控制位选和段选,实现动态数码管的显示,P2口连接了矩阵键盘,可以进行功能的拓展。

    注意,关于锁存器和数码管无法正常工作的问题,在图1中P0口接了8个上拉电阻,原因是P0口内部没有上拉电阻或电阻不够,如果不外接一个上拉电阻,P0口有可能只能输出低电平和悬空状态,无法输出高电平,而实验中所选用的数码管是共阴极的数码管,会导致数码管不能工作,如果有类似问题出现,可尝试接上上拉电阻。

    接有锁存器的动态数码管显示:

    动态显示原理图.png

    动态显示电路如图,共8个共阴极数码管,采用两片74LS573进行驱动,74LS573与74LS373都是8D锁存器,只是573引脚排列更易于布线。其引脚功能为:D1-D8为数据输入端;Q1-Q8为数据输出端;LE为数据输入锁存端,LE=1数据输入D锁存器,LE=0数据不能输入D锁存器,即LE下降沿锁存当前输入数据;地址输出允许端,-OE=0输出锁存数据,-OE=1输出高阻。
    电路中,U1输出段码a b c d e f g db,控制显示的字形与小数点,U2输出位选码,控制第几个数码管显示。单片机P1.4、P1.5分别连接到U1、U2的LE,P1.3连接U1和U2的-OE。根据硬件电路,动态显示编程时,应:① P1.3=1,U1、U2输出高阻;② P1.4=1,P0口输出段码,P1.4=0,U1锁存输入的段码;③ P1.5=1,P0口输出位选码,P1.5=0,U2锁存输入的位选码;④ P1.3=0,U1、U2同时输出段码和位选码,进行显示,经过一段时间后,再对另一个数码管做同样的操作。

    矩阵键盘

    矩阵键盘原理图.png

    程序源代码

    #include"reg51.h"
    #include"intrins.h"
    #define uchar unsigned  char
    #define uint unsigned int
    sbit OE = P1^3;
    sbit LE1 = P1^4;
    sbit LE2 = P1^5;
    data uchar h,m,i,s;
    uchar code dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
    uchar code reg[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
    void show();
    void delay(uint t){
        uchar i;
        while(t--)
            for(i=0;i<200;i++);
    }
    
    void main(){
    
    while(1){
        TMOD=0x01;                  // 设置定时器T0为方式1定时
        TH0=(65536-50000)/256;      // 给T0装入初值
        TL0=(65536-50000)%256;      // 给T0装入初值
        ET0=1;                      // 允许T0中断
        TR0=1;
        EA=1;
        show();
    }                       //CPU开中断        
    }
    void  T0_int(void)  interrupt 1 
      { 
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        i++;
        if(i==20)                       //1s时间
        { i=0;
          s++; 
        }
        if(s==60)                       //1s时间
        { s=0;
          m++; 
        }
        if(m==60)                       //1s时间
        { m=0;
          h++; 
        }
      }
    
    
    void show()
    {
        uint i;
    
        for(i=0;i<8;i++)
        {   
               OE = 1;
               LE2 = 1;
               OE = 0;
                P0=~reg[i];
               LE2 = 0;
               OE=1;
               LE1 = 1;
               OE = 0;
                //OE =0;    
            if(i==2||i==5)
            {
            P0=0x40;//发送段码
            delay(4); //间隔一段时间扫描    
    
            }
            if(h<10)
            {
               if(i==7) 
            {
            P0=dis_code[0];//发送段码
            delay(4); //间隔一段时间扫描    
    
            }
             if(i==6) 
            {
            P0=dis_code[h];//发送段码
            delay(4); //间隔一段时间扫描    
        
            }
    
            }
            if(m<10)
            {
               if(i==4) 
            {
            P0=dis_code[0];//发送段码
            delay(4); //间隔一段时间扫描    
    
            }
             if(i==3) 
            {
            P0=dis_code[m];//发送段码
            delay(4); //间隔一段时间扫描    
        
            }
    
            }
            if(s<10)
            {
                if(i==1) 
            {
            P0=dis_code[0];//发送段码
            delay(4); //间隔一段时间扫描    
        
            }
             if(i==0) 
            {
            P0=dis_code[s];//发送段码
            delay(4); //间隔一段时间扫描    
        
            }
            }
            if(h>=10)
                {
                   if(i==7) 
                {
                P0=dis_code[h/10];//发送段码
                delay(4); //间隔一段时间扫描    
        
                }
                 if(i==6) 
                {
                P0=dis_code[h%10];//发送段码
                delay(4); //间隔一段时间扫描    
            
                }
                if(h>=24)h=0;
                }
        if(m>=10)
                {
                if(i==4) 
                {
                P0=dis_code[m/10];//发送段码
                delay(4); //间隔一段时间扫描    
        
                }
                if(i==3) 
                {
                P0=dis_code[m%10];//发送段码
                delay(4); //间隔一段时间扫描    
        
                }
                if(m>60)m=1;
                }
        if(s>=10)
                {
                if(i==1) 
                {
                P0=dis_code[s/10];//发送段码
                delay(4); //间隔一段时间扫描    
    
                }
                if(i==0) 
                {
                P0=dis_code[s%10];//发送段码
                delay(4); //间隔一段时间扫描    
    
                }
                if(s>60)s=1;
                }
            //  delay(100);
                OE=0;
            }
        }
    
    

    注意:如果在仿真实验中数码管无法一起点亮,可能是延时需要改进,延时的总数在300-400之间合适,比如本实验的延时函数中是100个数,那么在外层自定义的数就定在4,共延时400个数,延时函数需要根据实验的不同进行调整。

    程序相对简易,没有使用算法,主要思想就是将时、分、秒作为全局变量,在定时器中计时,通过单独的显示函数来显示,主函数只进行中断开关和调用显示函数,所以代码相对易懂,需要注意的是,在定时的过程中,当时间到达最大时需要及时归零,比如计时到达60s是要将秒的全局变量归零,另外,想要做闹钟或者定时器的朋友可以沿用本实验电路和代码,矩阵键盘已连接,只需在代码加入矩阵键盘的操作就能实现想要的功能。

    相关文章

      网友评论

        本文标题:单片机实现秒表计时

        本文链接:https://www.haomeiwen.com/subject/dcxabctx.html