• 数码管、按键、定时器、ds18b20综合应用


    利用 8051 单片机设计秒表,包括 3 个按键、3 位数码管。按键分别用于启动、暂停、
    显示学号,显示温度,时间用数码管显示。开始后显示学号后 3 位。按启动键下后,显示 0.00 以 0.01
    秒的频率从 0.00 递增,期间按暂停键时暂停,再次按暂停继续递增,当递增到 9.99 以后循
    环。按显示学号键,显示学号。

    1、电路仿真:

     2、程序设计:

    (1)项目结构:

     (2)主函数:

    #include <reg52.h>
    #define uchar unsigned char
    #define uint unsigned int
    #include<display.c>
    #include<key.c>
    #include<DS18B20.C>
    unsigned int cp;
    void display(void);
    void key(void);
    /*Timer0中断服务函数*/
    void timer0_isr(void) interrupt 1
    {
        TH0=(65535-2000)/256;         //重装初值
        TL0=(65535-2000)%256;         //重装初值
        cp++;    //2000代表2ms,1000ms=1s
        if(mode == 2)cp=0;//按下暂停按键后,mode为2
        else{
            if(cp>=5)                      //0.01s到了
        {
             cp=0;
            xiaoshu++;
        }
        if(xiaoshu>=50)                 //1s到了
        {
            xiaoshu=0;
            sec++;                          //秒+1
            flash=~flash;
            get_ds18b20();                    
            if((a & 0x80) == 0x80)        
            {
                t_x = 0xff - a;            
                b = (0x0f - b)*0.625;   
            }
            else {t_x = a;b = b*0.625;}    
        }
        if(sec>=10)    sec=0;              //10S到了
        }
        
        P0=0xff;                
        display();                 //调用display函数
    } 
    
    /*******timer0初始化函数********/
    void timer0_init(void)
    {
        TMOD=0x01;                     //T0工作方式1
        TH0=(65535-2000)/256;         //对机器脉冲计数2000个积满溢出引发中断
        TL0=(65535-2000)%256;
        EA=1;   //开总中断
        ET0=1;   //开T0中断
        TR0=1;    //启动定时器
    }
    
    /******主函数********/
    void main()
    {
        
        timer0_init();                 //调用timer0_init 中断函数
    
        while(1)
        {
            
            key();                         //调用按键函数    
        }
        
        
    }

    (3)显示函数:

    采用的是动态显示方式(段选、位选),运用switch   case 结构来实现数码管的显示,与按键结合,不同的mode值显示不同的数字。

    #include <reg52.h>
    unsigned char i,j,xuehao = 113,xiaoshu = 0,sec = 0,flash,mode;
    unsigned char t_x,a,b;
    unsigned char code seven_seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};  
    void display(void)
    {
          if(mode == 0)//mode初始化默认为零,显示学号
          {
            switch(i)
            {
                case 0:P0 = seven_seg[xuehao%10];P1 = 0x04;break;//个位
                case 1:P0 = seven_seg[xuehao/10%10];P1 = 0x02;break;//十位
                case 2:P0 = seven_seg[xuehao/100];P1 = 0x01;break;//
            }
            i++;
            if(i>=3)i = 0;
          }
            
          if(mode == 1)
          {
            switch(j)
            {
                case 0:P0 = seven_seg[xiaoshu%10];P1 = 0x04;break;
                case 1:P0 = seven_seg[xiaoshu/10];P1 = 0x02;break;
                case 2:P0 = seven_seg[sec]&(0x7F | flash);P1 = 0x01;break;
            }
            j++;
            if(j>=3)j = 0;
          }
            
          if(mode == 2)
          {
            switch(j)
            {
                case 0:P0 = seven_seg[xiaoshu%10];P1 = 0x04;break;
                case 1:P0 = seven_seg[xiaoshu/10];P1 = 0x02;break;
                case 2:P0 = seven_seg[sec]&(0x7F | flash);P1 = 0x01;break;
            }
            j++;
            if(j>=3)j = 0;
          }
            
            
              if(mode == 3)
          {
            switch(j)
            {
                case 0:P0 = seven_seg[b];P1 = 0x08;break;
                case 1:P0 = seven_seg[t_x % 10]& 0x7f;P1 = 0x04;break;
                case 2:P0 = seven_seg[t_x / 10];P1 = 0x02;break;
                case 3:P1 = 0x01;if((a & 0x80) == 0x80)P0 = 0xbf;                
                   else P0 = 0xff;break;
                  
            }
                
            j++;
            if(j>=4)j = 0;
          }
            
            
            
            
    }

    (4)按键:

    采用按键按下有效的方式,都标志位mode的值进行修改。

    #include <reg52.h>
    sbit key1 = P2^3; //启动
    sbit key2 = P2^4;//暂停
    sbit key3 = P2^5;//显示学号
    sbit key4 = P2^6;//显示WENDU
    unsigned char mode;
    void delay(unsigned int x)//delay函数实现短暂的延时(不精确,通过程序的执行次数累积出延时的时间)
    {
    while(x--);
    }

    void key(void)//采用按键按下有效的方式
    {
    if(key1 == 0) //启动键(如果按键按下)
    {
    delay(400); //消抖
    if(key1 == 0)//消抖后,如果确定按键真的按下了
    {
    mode=1;
    }
    while(key1 == 0);//再按,不起作用,一直执行while
    }

    if(key2 == 0) //暂停键
    {
    delay(400); //消抖
    if(key2 == 0)
    {
    mode = 2;
    }
    while(key2 == 0);//再按,不起作用
    }

    if(key3 == 0) //显示学号
    {
    delay(400); //消抖
    if(key3 == 0)
    {
    mode = 0;
    }
    while(key3 == 0);//再按,不起作用
    }
    if(key4 == 0) //显示温度
    {
    delay(400); //消抖
    if(key4 == 0)
    {
    mode = 3;
    }
    while(key3 == 0);//再按,不起作用
    }
    }

    (5)ds18b20驱动程序:

    uchar a,b;
    sbit DQ = P3^7;              
    void ds18b20_init(void)
    {
         uchar x = 255;                    
        DQ = 1;                                
        DQ = 0;                            
        delay(80);                                     
        DQ = 1;                                         
        delay(5);                                    
        while(DQ && x--);                              
        delay(20);                                      
        DQ = 1;                                    
    }
    uchar read_onechar(void)                  
    {
         uchar i,j;                              
        for(i = 0;i < 8;i++)                          
        {                                              
             DQ = 0;                                      
            delay(1);                                  
            DQ = 1;                                     
            j = j>>1;                                
            if(DQ == 1)j = j | 0x80;                  
            delay(5);                                  
            DQ = 1;                                     
        }
        DQ = 1;                                    
        return(j);                                
    }
    void write_onechar(uchar x)                 
    {
         uchar i;                        
        for(i = 0;i < 8;i++)                          
        {
             DQ = 0;                                      
            DQ = (bit)(x & 0x01);                     
            x = x >> 1;                                 
            delay(10);                        
            DQ = 1;                                     
        }
        DQ = 1;                                         
    }
    void get_ds18b20(void)                             
    {
         uchar i;                            
        ds18b20_init();                                        
        write_onechar(0xcc);                           
        write_onechar(0x44);                               
        ds18b20_init();                                  
        write_onechar(0xcc);                           
        write_onechar(0xbe);                         
        a = read_onechar();                          
        b = a & 0x0f;                               
        i = read_onechar();                             
        a  = (i << 4) | (a >> 4);                  
    }
  • 相关阅读:
    java方法参数传值传引用的一点看法
    Oracle触发器介绍
    CASE WHEN
    group by ,order by ,having
    Java中使用正则表达式
    Oracle 9i 分析函数参考手册
    ORACLE round 与 trunc 的区别
    oracle的默认表名长度(30)
    order by 使用索引的情况
    解析oracle的ROWNUM 作者: chen_liang
  • 原文地址:https://www.cnblogs.com/zhai1997/p/12128009.html
Copyright © 2020-2023  润新知