基于单片机实验板的液晶屏显示时间、日期、温度并支持按键控制

目录

  • 前言:
  • 本代码涉及的主要知识:
  • proteus模拟实验板:
  • 代码(实验板实现代码):
  • 代码(时间 + 日期):
  • 代码(时间显示 + 日期显示 + 按键控制):
  • 代码(温度显示):
  • 代码汇总(时间显示 + 日期显示 + 按键控制 + 温度显示)[有bug]:
  • 代码汇总 正解(时间显示 + 日期显示 + 按键控制 + 温度显示):
  • 总结:
  • 前言:


    设计本代码的主要目的是为了完成期末作业,即在液晶显示屏上显示、时间、日期、温度,以及用按键控制时间、温度的显示。总的来说就是对前面学习计数的糅合,本代码实现的是显示时间,并能在实验板上成功显示。


    本代码涉及的主要知识:


    1.液晶显示屏模块应用

    主要是学会如何在液晶显示屏上显示内容

    2.T1中断函数的使用

    主要通过T1中断函数记录时间,即通过每次的溢出参产生中断来记录秒的变化。

    3.通过数组记录时、分、秒,再通过%/来取值显示

    4.行列键盘

    5.温度显示


    proteus模拟实验板:

    上述模拟板是某个大哥按照实验板模拟的,主要以它代替真实实验板。


    代码(实验板实现代码):

    #include<reg52.h>
    
    unsigned char code table[]="0123456789:-";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    unsigned char count = 0; 
    unsigned char time[] = {23, 58, 50};//初始时间
    
    void delay(unsigned int x){//延时函数 
         unsigned int i;
         for (i=x; i>0;i--);
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0= com;
         RS=0;RW=0;EN=1;
         delay(200);
         EN=0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS=1;RW=0;EN=1;
         delay (200);
         EN=0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                time[0] = 0;
                }
             }
           } 
        }
    }
    
    void dispaly(){//显示时间函数 
       init();
       write_com(0x80);
       write_date(table[time[0] / 10]);
       delay(3000);
       write_date(table[time[0] % 10]);
       delay(3000);
       write_date(table[10]);
       delay(3000);
       write_date(table[time[1] / 10]);
       delay(3000);
       write_date(table[time[1] % 10]);
       delay(3000);
       write_date(table[10]);
       delay(3000);
       write_date(table[time[2] / 10]);
       delay(3000);
       write_date(table[time[2] % 10]);
       delay(3000);
       write_com(0x02);	
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    void main()
    {
     intpt_begin();
      while(1){
       dispaly();
     }
    }
    


    后续的显示日期和显示时间的原理大致相同,添加按键也无非多用几个引脚,难点主要是温度显示,后续有时间学习一下。


    代码(时间 + 日期):

    #include<reg52.h>
    
    unsigned char code table[]="0123456789:/";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    unsigned char count = 0; 
    unsigned char time[] = {23, 58, 50};
    unsigned int date[] = {2023, 5, 20};
    unsigned char year[] = {0, 0, 0, 0};
    unsigned int years = 0;
    unsigned int i;
    
    void delay(unsigned int x){//延时函数 
        
         for (i=x; i>0;i--);
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                time[0] = 0;
                }
             }
           } 
        }
    }
    
    void dispaly_1(){//显示时间函数,显示第一层 
       write_com(0x80);//起点为第一行第一个字符 
       write_date(table[time[0] / 10]);
       delay(3000);
       write_date(table[time[0] % 10]);
       delay(3000);
       write_date(table[10]);
       delay(3000);
       write_date(table[time[1] / 10]);
       delay(3000);
       write_date(table[time[1] % 10]);
       delay(3000);
       write_date(table[10]);
       delay(3000);
       write_date(table[time[2] / 10]);
       delay(3000);
       write_date(table[time[2] % 10]);
       delay(3000);
       write_com(0x02);	
    }
     
    void dispaly_2(){
       write_com(0xc0);	//起点为第二行第一个字符
       years = date[0];
       
       for(i = 0; i < 4; i ++){
       	  year[i] = years % 10;
       	  years = years / 10;
       }  
         
    //    for(i = 3; i >= 0; i --) {
    //      	write_date(table[year[i]]);
    //      	delay(3000);
    //    } 
        
       	write_date(table[year[3]]);
       	delay(3000);
        write_date(table[year[2]]);
        delay(3000);
    	write_date(table[year[1]]);
       	delay(3000);
    	write_date(table[year[0]]);
       	delay(3000); 
        
       write_date(table[11]);
       delay(3000);
       
      write_date(table[date[1] / 10]);
      delay(3000); 
      write_date(table[date[1] % 10]);
      delay(3000);  
      
      write_date(table[11]);
      delay(3000); 
       
      write_date(table[date[2] / 10]);
      delay(3000); 
      write_date(table[date[2] % 10]);
      delay(3000); 
      
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    void main()
    {
     intpt_begin();//开中断 
      while(1){
       init();
       dispaly_1();
       dispaly_2();
     }
    }
    


    代码(时间显示 + 日期显示 + 按键控制):

    1、按键控制主要基于单片机的行列键盘的原理,即通过扫描找到键位。
    由于实验板的按键排布与书本上的案件排布不同,所以要对书上的代码进行一定的修改。

    2.本代码设立了七个按键(从左至右,从上至下),分别能对时间的时、分、秒和日期的年、月、日进行控制。

    3.本代码时间的变化会影响日期的变化,年份(平闰)会影响二月份(28、29)天数的变化。

     #include<reg52.h>
    
    unsigned char code table[]="0123456789:/";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    unsigned char count = 0; 
    unsigned char time[] = {23, 59, 30};
    unsigned int date[] = {2023, 12, 31};
    unsigned char year[] = {0, 0, 0, 0};
    unsigned int years = 0;
    unsigned int i,j;
    unsigned char net = 0;//按键 
    
    char key_buf[]={0x77, 0x7b, 0x7d, 0x7e, 0xb7, 0xbb, 0xbd, 0xbe, 0xd7, 0xdb, 0xdd, 0xde, 0xe7, 0xeb, 0xed, 0xee};//0-15
    char month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    char key = 0;
    
    void delay(unsigned int x){//延时函数 
         for (i=x; i>0;i--);
    }
    
    void month_change(){//判别闰平年 
    	if(date[0] % 4 == 0 && date[0] % 100 != 0 || date[0] % 400 == 0) month[2] = 29;
    	else month[2] = 28;
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                  time[0] = 0;
                  date[2] = date[2] + 1;
       	          if(date[2] >= month[date[1]] + 1){
       		        date[2] = 1;
       		        date[1] = date[1] + 1;
       		        if(date[1] >= 13){
       		        	date[1] = 1;
       		        	date[0] = date[0] + 1;
       		        	if(date[0] >= 9999){
       		        		date[0] = 2023;
    					   }
    				   }
    	           }
                }
             }
           } 
        }
    }
    
    void dispaly_1(){//显示时间函数,显示第一层 
       write_com(0x80);//起点为第一行第一个字符 
       write_date(table[time[0] / 10]);
       delay(6000);
       write_date(table[time[0] % 10]);
        delay(6000);
       write_date(table[10]);
       delay(6000);
       write_date(table[time[1] / 10]);
       delay(6000);
       write_date(table[time[1] % 10]);
       delay(6000);
       write_date(table[10]);
        delay(6000);
       write_date(table[time[2] / 10]);
        delay(6000);
       write_date(table[time[2] % 10]);
        delay(6000);
       write_com(0x02);	
    }
     
    void dispaly_2(){
       write_com(0xc0);	//起点为第二行第一个字符
       years = date[0];
       
       for(i = 0; i < 4; i ++){
       	  year[i] = years % 10;
       	  years = years / 10;
       }  
         
        
       	write_date(table[year[3]]);
         delay(6000);
        write_date(table[year[2]]);
         delay(6000);
    	write_date(table[year[1]]);
       	 delay(6000);
    	write_date(table[year[0]]);
       	 delay(6000);
        
       write_date(table[11]);
        delay(6000);
       
      write_date(table[date[1] / 10]);
       delay(6000);
      write_date(table[date[1] % 10]);
       delay(6000); 
      
      write_date(table[11]);
       delay(6000);
      write_date(table[date[2] / 10]);
       delay(6000); 
      write_date(table[date[2] % 10]);
       delay(6000);
      
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    char getKey(void)
    {
     char key_scan[]={0xef,0xdf,0xbf,0x7f};
     for(i = 0;i < 4; i++)
     {
      P1 = key_scan[i];
      if((P1 & 0x0f) != 0x0f)
      {
       for(j = 0; j < 16; j++)
       {
        if(key_buf[j] == P1)
         return j;
       }
      }
     }
     return -1;
    }
    
    void key_control(){
    	if(key == 0){
          	time[0] = time[0] + 1;
            if(time[0] >= 24){
              time[0] = 0;
    	   }
       }
       	if(key == 1){
          	time[1] = time[1] + 1;
            if(time[1] >= 60){
              time[1] = 0;
    	   }
       }
       	if(key == 2){
            time[2] = 0;
    	   }
    	   
       	if(key == 3){
           date[0] = date[0] + 1;
           if(date[0] >= 9999){
           	date[0] = 2023;
    	   }
       }
       if(key == 4){
       	date[0] = date[0] - 1;
           if(date[0] <= 1000){
           	date[0] = 2023;
    	   }
       }
       
       if(key == 5){
       	date[1] = date[1] + 1;
       	if(date[1] >= 13){
       		date[1] = 1;
    	   }
       }
       if(key == 6){
       	date[2] = date[2] + 1;
       	if(date[2] >= month[date[1]] + 1){
       		date[2] = 1;
    	   }
       }
    }
    
    void main()
    {
     intpt_begin();//开中断 
      while(1){
       init();
       month_change(); 
       dispaly_1();
       dispaly_2();
       key =  getKey();
       if(key != -1) key_control();
     }
    }
    

    —— 2023.5.21


    代码(温度显示):

    主要通过对温度传感器的控制让其读取温度,再将读取的温度转化,并在显示屏上显示

    #include<reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    typedef unsigned char uint8;
    typedef unsigned int uint16;
    sbit DQ=P3^7;  //定义数据线
    int j = 0;
    uint8 temp[]=	   "wd:00";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    long tmp = 0;  //存储温度值
    
     void delay(uint16 time)
    {
    	while(time--);
    }
                                          
    uint8 DS18B20_init()
    {
    	uint8 ans;
    	DQ = 1;
    	delay(1);
    	DQ = 0;
    	delay(100);
    	DQ = 1;
    	delay(6);
    	ans = DQ;
    	delay(100);
    	if(!ans)
    		return 1;
    	else
    		return 0;
    }
    
    void DS18B20_write(uint8 date)
    {
    	uint8 i;
    	DQ = 1;
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
    	{
    		DQ = 0;
    		if(date&0x01)  //从低到高取出数据的每位
    			DQ = 1;
    		else
    			DQ = 0;
    		delay(10);
    		DQ = 1;
    		date >>= 1;
    		delay(1);
    	}
    }
    
    uint8 DS18B20_read()
    {
    	uint8 i,date = 0;
    	DQ = 1;  //释放总线
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
    	{
    		DQ = 0;
    		date >>= 1;
    		DQ = 1;
    		if(DQ)
    			date |= 0x80;  //将data的一位置1
    		delay(8);
    		DQ = 1;
    		delay(1);
    	}
    	return date;  //返回读出的数
    }
    
    void DS18B20_check()
    {
    	uint8 date1,date2;
    	float ta;
    	if(DS18B20_init())
    	{
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0x44);  //启动温度转换
    		DS18B20_init();  //复位
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0xbe);  //启动读取温度
    		date1 = DS18B20_read();  //读取两个温度字节
    		date2 = DS18B20_read();
    		tmp = date2;
    		tmp <<= 8;
    		tmp = tmp|date1;
    		ta = tmp*0.0625;
    		tmp = ta*1000;
    	}
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    
    void dispaly_3(){//显示时间函数,显示第一层 
       temp[3] = 0x30 + tmp / 10000;
       temp[4] = 0x30 + tmp / 1000 % 10;
        write_com(0x80);//起点为第一行第一个字符 
       for(j = 0; j < 5; j ++){
         write_date(temp[j]);
         delay(3000);	
       }  
       write_com(0x02);
    }
     
    void main()
    {
      
      DS18B20_init();  //DS18B20初始化
      DS18B20_write(0xcc);  //跳过序列号
      DS18B20_write(0x44);  //启动温度转换
      while(1){
       init();
       DS18B20_check();  //从DS18B20中读取温度
       dispaly_3();
     }
    }
    
    

    ———— 2023.5.21

    本代码参考:基于51单片机的温控系统


    代码汇总(时间显示 + 日期显示 + 按键控制 + 温度显示)[有bug]:

    温度显示需要在上述代码的基础上往后移动11位
    此代码秒不能动,还未发现问题所在,正在寻找

    #include<reg51.h>
    #define uchar unsigned char
    #define uint unsigned int
    typedef unsigned char uint8;
    typedef unsigned int uint16;
    sbit DQ=P3^7;  //定义数据线
    int j = 0;
    int k = 0;
    uint8 temp[]=	   "wd:00";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    long tmp = 0;  //存储温度值
    unsigned int years = 0;
    unsigned char code table[]="0123456789:/";
    
    unsigned char count = 0; 
    unsigned char time[] = {23, 59, 30};
    unsigned int date[] = {2023, 12, 31};
    unsigned char year[] = {0, 0, 0, 0};
    
    char key_buf[]={0x77, 0x7b, 0x7d, 0x7e, 0xb7, 0xbb, 0xbd, 0xbe, 0xd7, 0xdb, 0xdd, 0xde, 0xe7, 0xeb, 0xed, 0xee};//0-15
    char month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    char key = 0;
     
     void delay(unsigned int time)
    {
    	while(time--);
    }
                                          
    uint8 DS18B20_init()
    {
    	uint8 ans;
    	DQ = 1;
    	delay(1);
    	DQ = 0;
    	delay(100);
    	DQ = 1;
    	delay(6);
    	ans = DQ;
    	delay(100);
    	if(!ans)
    		return 1;
    	else
    		return 0;
    }
    
    void DS18B20_write(uint8 date)
    {
    	uint8 i;
    	DQ = 1;
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
    	{
    		DQ = 0;
    		if(date&0x01)  //从低到高取出数据的每位
    			DQ = 1;
    		else
    			DQ = 0;
    		delay(10);
    		DQ = 1;
    		date >>= 1;
    		delay(1);
    	}
    }
    
    uint8 DS18B20_read()
    {
    	uint8 i,date = 0;
    	DQ = 1;  //释放总线
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
    	{
    		DQ = 0;
    		date >>= 1;
    		DQ = 1;
    		if(DQ)
    			date |= 0x80;  //将data的一位置1
    		delay(8);
    		DQ = 1;
    		delay(1);
    	}
    	return date;  //返回读出的数
    }
    
    void DS18B20_check()
    {
    	uint8 date1,date2;
    	float ta;
    	if(DS18B20_init())
    	{
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0x44);  //启动温度转换
    		DS18B20_init();  //复位
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0xbe);  //启动读取温度
    		date1 = DS18B20_read();  //读取两个温度字节
    		date2 = DS18B20_read();
    		tmp = date2;
    		tmp <<= 8;
    		tmp = tmp|date1;
    		ta = tmp*0.0625;
    		tmp = ta*1000;
    	}
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    
    void dispaly_3(){//显示时间函数,显示第一层 
       temp[3] = 0x30 + tmp / 10000;
       temp[4] = 0x30 + tmp / 1000 % 10;
        write_com(0x8b);//起点为第一行第一个字符 
       for(j = 0; j < 5; j ++){
         write_date(temp[j]);
         delay(3000);	
       }  
       write_com(0x02);
    }
    
    void month_change(){//判别闰平年 
    	if(date[0] % 4 == 0 && date[0] % 100 != 0 || date[0] % 400 == 0) month[2] = 29;
    	else month[0] = 28;
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                  time[0] = 0;
                  date[2] = date[2] + 1;
       	          if(date[2] >= month[date[1]] + 1){
       		        date[2] = 1;
       		        date[1] = date[1] + 1;
       		        if(date[1] >= 13){
       		        	date[1] = 1;
       		        	date[0] = date[0] + 1;
       		        	if(date[0] >= 9999){
       		        		date[0] = 2023;
    					   }
    				   }
    	           }
                }
             }
           } 
        }
    }
    
    void dispaly_1(){//显示时间函数,显示第一层 
       write_com(0x80);//起点为第一行第一个字符 
       write_date(table[time[0] / 10]);
       delay(6000);
       write_date(table[time[0] % 10]);
        delay(6000);
       write_date(table[10]);
       delay(6000);
       write_date(table[time[1] / 10]);
       delay(6000);
       write_date(table[time[1] % 10]);
       delay(6000);
       write_date(table[10]);
        delay(6000);
       write_date(table[time[2] / 10]);
        delay(6000);
       write_date(table[time[2] % 10]);
        delay(6000);
       write_com(0x02);	
    }
     
    void dispaly_2(){
       write_com(0xc0);	//起点为第二行第一个字符
       years = date[0];
       
       for(j = 0; j < 4; j ++){
       	  year[j] = years % 10;
       	  years = years / 10;
       }  
         
        
       	write_date(table[year[3]]);
         delay(6000);
        write_date(table[year[2]]);
         delay(6000);
    	write_date(table[year[1]]);
       	 delay(6000);
    	write_date(table[year[0]]);
       	 delay(6000);
        
       write_date(table[11]);
        delay(6000);
       
      write_date(table[date[1] / 10]);
       delay(6000);
      write_date(table[date[1] % 10]);
       delay(6000); 
      
      write_date(table[11]);
       delay(6000);
      write_date(table[date[2] / 10]);
       delay(6000); 
      write_date(table[date[2] % 10]);
       delay(6000);
      
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    char getKey(void)
    {
     char key_scan[]={0xef,0xdf,0xbf,0x7f};
     for(k = 0;k < 4; k++)
     {
      P1 = key_scan[k];
      if((P1 & 0x0f) != 0x0f)
      {
       for(j = 0; j < 16; j++)
       {
        if(key_buf[j] == P1)
         return j;
       }
      }
     }
     return -1;
    }
    
    void key_control(){
    	if(key == 0){
          	time[0] = time[0] + 1;
            if(time[0] >= 24){
              time[0] = 0;
    	   }
       }
       	if(key == 1){
          	time[1] = time[1] + 1;
            if(time[1] >= 60){
              time[1] = 0;
    	   }
       }
       	if(key == 2){
            time[2] = 0;
    	   }
    	   
       	if(key == 3){
           date[0] = date[0] + 1;
           if(date[0] >= 9999){
           	date[0] = 2023;
    	   }
       }
       if(key == 4){
       	date[0] = date[0] - 1;
           if(date[0] <= 1000){
           	date[0] = 2023;
    	   }
       }
       
       if(key == 5){
       	date[1] = date[1] + 1;
       	if(date[1] >= 13){
       		date[1] = 1;
    	   }
       }
       if(key == 6){
       	date[2] = date[2] + 1;
       	if(date[2] >= month[date[1]] + 1){
       		date[2] = 1;
    	   }
       }
    }
     
    void main()
    {
      
      DS18B20_init();  //DS18B20初始化
      DS18B20_write(0xcc);  //跳过序列号
      DS18B20_write(0x44);  //启动温度转换
      while(1){
       init();
       month_change(); 
       dispaly_1();
        DS18B20_check();  //从DS18B20中读取温度
       dispaly_3();
       dispaly_2();
       key =  getKey();
       if(key != -1) key_control();
     }
    }
    
    

    —— 2023.5.21


    代码汇总 正解(时间显示 + 日期显示 + 按键控制 + 温度显示):

    解决了显示问题,让整个显示过程更加连贯
    处理方法:把中断函数开启函数放到了while循环的外部。

     #include<reg52.h>
    
    unsigned char code table[]="0123456789:/";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    unsigned char count = 0; 
    unsigned char time[] = {23, 59, 30};
    unsigned int date[] = {2023, 12, 31};
    unsigned char year[] = {0, 0, 0, 0};
    unsigned int years = 0;
    unsigned int i,j;
    unsigned char net = 0;//按键 
    
    char key_buf[]={0x77, 0x7b, 0x7d, 0x7e, 0xb7, 0xbb, 0xbd, 0xbe, 0xd7, 0xdb, 0xdd, 0xde, 0xe7, 0xeb, 0xed, 0xee};//0-15
    char month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    char key = 0;
    
    
    #define uchar unsigned char
    #define uint unsigned int
    typedef unsigned char uint8;
    typedef unsigned int uint16;
    sbit DQ=P3^7;  //定义数据线
    
    char k = 0;
    
    uint8 temp[]=	   "wd:00";
    long tmp = 0;  //存储温度值
    
    void delay(unsigned int x){//延时函数 
         for (i=x; i>0;i--);
    }
    
    void month_change(){//判别闰平年 
    	if(date[0] % 4 == 0 && date[0] % 100 != 0 || date[0] % 400 == 0) month[2] = 29;
    	else month[2] = 28;
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0f);
         write_com(0x06);
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                  time[0] = 0;
                  date[2] = date[2] + 1;
       	          if(date[2] >= month[date[1]] + 1){
       		        date[2] = 1;
       		        date[1] = date[1] + 1;
       		        if(date[1] >= 13){
       		        	date[1] = 1;
       		        	date[0] = date[0] + 1;
       		        	if(date[0] >= 9999){
       		        		date[0] = 2023;
    					   }
    				   }
    	           }
                }
             }
           } 
        }
    }
    
    void dispaly_1(){//显示时间函数,显示第一层 
       write_com(0x80);//起点为第一行第一个字符 
       write_date(table[time[0] / 10]);
       delay(6000);
       write_date(table[time[0] % 10]);
        delay(6000);
       write_date(table[10]);
       delay(6000);
       write_date(table[time[1] / 10]);
       delay(6000);
       write_date(table[time[1] % 10]);
       delay(6000);
       write_date(table[10]);
        delay(6000);
       write_date(table[time[2] / 10]);
        delay(6000);
       write_date(table[time[2] % 10]);
        delay(6000);
       write_com(0x02);	
    }
     
    void dispaly_2(){
       write_com(0xc0);	//起点为第二行第一个字符
       years = date[0];
       
       for(i = 0; i < 4; i ++){
       	  year[i] = years % 10;
       	  years = years / 10;
       }  
         
        
       	write_date(table[year[3]]);
         delay(6000);
        write_date(table[year[2]]);
         delay(6000);
    	write_date(table[year[1]]);
       	 delay(6000);
    	write_date(table[year[0]]);
       	 delay(6000);
        
       write_date(table[11]);
        delay(6000);
       
      write_date(table[date[1] / 10]);
       delay(6000);
      write_date(table[date[1] % 10]);
       delay(6000); 
      
      write_date(table[11]);
       delay(6000);
      write_date(table[date[2] / 10]);
       delay(6000); 
      write_date(table[date[2] % 10]);
       delay(6000);
      
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    char getKey(void)
    {
     char key_scan[]={0xef,0xdf,0xbf,0x7f};
     for(k = 0;k < 4; k++)
     {
      P1 = key_scan[k];
      if((P1 & 0x0f) != 0x0f)
      {
       for(j = 0; j < 16; j++)
       {
        if(key_buf[j] == P1)
         return j;
       }
      }
     }
     return -1;
    }
    
    void key_control(){
    	if(key == 0){
          	time[0] = time[0] + 1;
            if(time[0] >= 24){
              time[0] = 0;
    	   }
       }
       	if(key == 1){
          	time[1] = time[1] + 1;
            if(time[1] >= 60){
              time[1] = 0;
    	   }
       }
       	if(key == 2){
            time[2] = 0;
    	   }
    	   
       	if(key == 3){
           date[0] = date[0] + 1;
           if(date[0] >= 9999){
           	date[0] = 2023;
    	   }
       }
       if(key == 4){
       	date[0] = date[0] - 1;
           if(date[0] <= 1000){
           	date[0] = 2023;
    	   }
       }
       
       if(key == 5){
       	date[1] = date[1] + 1;
       	if(date[1] >= 13){
       		date[1] = 1;
    	   }
       }
       if(key == 6){
       	date[2] = date[2] + 1;
       	if(date[2] >= month[date[1]] + 1){
       		date[2] = 1;
    	   }
       }
    }
    
    
    
    uint8 DS18B20_init()
    {
    	uint8 ans;
    	DQ = 1;
    	delay(1);
    	DQ = 0;
    	delay(100);
    	DQ = 1;
    	delay(6);
    	ans = DQ;
    	delay(100);
    	if(!ans)
    		return 1;
    	else
    		return 0;
    }
    
    void DS18B20_write(uint8 date)
    {
    	uint8 i;
    	DQ = 1;
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
    	{
    		DQ = 0;
    		if(date&0x01)  //从低到高取出数据的每位
    			DQ = 1;
    		else
    			DQ = 0;
    		delay(10);
    		DQ = 1;
    		date >>= 1;
    		delay(1);
    	}
    }
    
    uint8 DS18B20_read()
    {
    	uint8 i,date = 0;
    	DQ = 1;  //释放总线
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
    	{
    		DQ = 0;
    		date >>= 1;
    		DQ = 1;
    		if(DQ)
    			date |= 0x80;  //将data的一位置1
    		delay(8);
    		DQ = 1;
    		delay(1);
    	}
    	return date;  //返回读出的数
    }
    
    void DS18B20_check()
    {
    	uint8 date1,date2;
    	float ta;
    	if(DS18B20_init())
    	{
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0x44);  //启动温度转换
    		DS18B20_init();  //复位
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0xbe);  //启动读取温度
    		date1 = DS18B20_read();  //读取两个温度字节
    		date2 = DS18B20_read();
    		tmp = date2;
    		tmp <<= 8;
    		tmp = tmp|date1;
    		ta = tmp*0.0625;
    		tmp = ta*1000;
    	}
    }
    
    
    void dispaly_3(){//显示温度 
       temp[3] = 0x30 + tmp / 10000;
       temp[4] = 0x30 + tmp / 1000 % 10;
        write_com(0x8b);//起点为第一行第十一个字符 
       for(j = 0; j < 5; j ++){
         write_date(temp[j]);
         delay(3000);	
       }  
       write_com(0x02);
    }
     
    
    void main()
    {
    	
      DS18B20_init();  //DS18B20初始化
      DS18B20_write(0xcc);  //跳过序列号
      DS18B20_write(0x44);  //启动温度转换
     intpt_begin();//开中断 
      init();
      while(1){
       month_change(); 
       dispaly_1();
       DS18B20_check();  //从DS18B20中读取温度
       dispaly_3();
       dispaly_2();
       key =  getKey();//扫描键盘 
       if(key != -1) key_control();
     }
    }
    
    

    值得一提的是在模拟板上显示温度是0,实验板上温度完全没有问题,离谱的是实验板和模拟板都没有问题,离谱,还有就是本代码内部的一些语句若用for循环代替会乱码,也很离谱,反正最后能让板子显示就行了。

    优化版代码:

    优化了按键丝滑度、时间显示丝滑度、感谢给我提供帮助的大哥!

     #include<reg52.h>
    
    unsigned char code table[]="0123456789:/";
    sbit RS=P2^6;
    sbit RW=P2^5;
    sbit EN=P2^7;
    unsigned int count = 0; 
    unsigned char time[] = {23, 59, 30};
    unsigned int date[] = {2023, 12, 31};
    unsigned char year[] = {0, 0, 0, 0};
    unsigned int years = 0;
    unsigned int i,j;
    unsigned char net = 0;//按键 
    
    
    char key_buf[]={0x77, 0x7b, 0x7d, 0x7e, 0xb7, 0xbb, 0xbd, 0xbe, 0xd7, 0xdb, 0xdd, 0xde, 0xe7, 0xeb, 0xed, 0xee};//0-15
    char month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    
    char key = 0;
    
    
    #define uchar unsigned char
    #define uint unsigned int
    typedef unsigned char uint8;
    typedef unsigned int uint16;
    sbit DQ=P3^7;  //定义数据线
    
    char k = 0;
    
    uint8 temp[]=	   "T:00";
    long tmp = 0;  //存储温度值
    
    void delay(unsigned int x){//延时函数 
         for (i=x; i>0;i--);
    }
    
    void month_change(){//判别闰平年 
    	if(date[0] % 4 == 0 && date[0] % 100 != 0 || date[0] % 400 == 0) month[2] = 29;
    	else month[0] = 28;
    }
    
    void write_com (unsigned char com){//写指令函数 
         P0 = com;
         RS = 0;RW = 0;EN = 1;
         delay(200);
         EN = 0;
    }
    void write_date(unsigned char dat) {//写数据函数 
         P0 = dat;
         RS = 1;RW = 0;EN = 1;
         delay (200);
         EN = 0;
    }
    
    void init(){//初始化 
         write_com(0x01);
         write_com(0x38);
         write_com(0x0c);
         write_com(0x06);
    }
    
    timer1() interrupt 3{//T1中断函数 
         TH1 = 0x3C;
         TL1 = 0xB0;
         count = count + 1;
         if(count == 20){
            count = 0; 
            time[2] = time[2] + 1;
            if(time[2] >= 60){
              time[2] = 0;
              time[1] = time[1] + 1;
              if(time[1] >= 60){
                time[1] = 0;
                time[0] = time[0] + 1;
                if(time[0] >= 24){
                  time[0] = 0;
                  date[2] = date[2] + 1;
       	          if(date[2] >= month[date[1]] + 1){
       		        date[2] = 1;
       		        date[1] = date[1] + 1;
       		        if(date[1] >= 13){
       		        	date[1] = 1;
       		        	date[0] = date[0] + 1;
       		        	if(date[0] >= 9999){
       		        		date[0] = 2023;
    					   }
    				   }
    	           }
                }
             }
           } 
        }
    }
    
    void dispaly_1(){//显示时间函数,显示第一层 
       write_com(0x80);//起点为第一行第一个字符 
       write_date(table[time[0] / 10]);
       delay(1);
       write_date(table[time[0] % 10]);
        delay(1);
       write_date(table[10]);
        delay(1);
       write_date(table[time[1] / 10]);
        delay(1);
       write_date(table[time[1] % 10]);
       delay(1);
       write_date(table[10]);
        delay(1);
       write_date(table[time[2] / 10]);
         delay(1);
       write_date(table[time[2] % 10]);
         delay(1);
       write_com(0x02);	
    }
     
    void dispaly_2(){
       write_com(0xc0);	//起点为第二行第一个字符
       years = date[0];
       
       for(i = 0; i < 4; i ++){
       	  year[i] = years % 10;
       	  years = years / 10;
       }  
         
        
       	write_date(table[year[3]]);
         delay(1);
        write_date(table[year[2]]);
         delay(1);
    	write_date(table[year[1]]);
       	 delay(1);
    	write_date(table[year[0]]);
       	 delay(1);
        
       write_date(table[11]);
         delay(1);
       
      write_date(table[date[1] / 10]);
       delay(1);
      write_date(table[date[1] % 10]);
       delay(1);
      
      write_date(table[11]);
       delay(1);
      write_date(table[date[2] / 10]);
        delay(1);
      write_date(table[date[2] % 10]);
        delay(1);
      
    }
    
    void intpt_begin(){//开中断 
      TMOD = 0x10;
      TH1 = 0x3C;
      TL1 = 0xB0;
      EA = 1;
      ET1 = 1;
      TR1 = 1;	
    }
    
    char getKey(void)
    {
     char key_scan[]={0xef,0xdf,0xbf,0x7f};
     for(k = 0;k < 4; k++)
     {
      P1 = key_scan[k];
      if((P1 & 0x0f) != 0x0f)
      {
       for(j = 0; j < 16; j++)
       {
        if(key_buf[j] == P1)
         return j;
       }
      }
     }
     return -1;
    }
    
    void key_control(){
    	
     
    	
    	if(key == 0){
          	time[0] = time[0] + 1;
            if(time[0] >= 24){
              time[0] = 0;
    	   }
       }
       	if(key == 1){
          	time[1] = time[1] + 1;
            if(time[1] >= 60){
              time[1] = 0;
    	   }
       }
       	if(key == 2){
            time[2] = 0;
    	   }
    	   
       	if(key == 3){
           date[0] = date[0] + 1;
           if(date[0] >= 9999){
           	date[0] = 2023;
    	   }
       }
       if(key == 4){
       	date[0] = date[0] - 1;
           if(date[0] <= 1000){
           	date[0] = 2023;
    	   }
       }
       
       if(key == 5){
       	date[1] = date[1] + 1;
       	if(date[1] >= 13){
       		date[1] = 1;
    	   }
       }
       if(key == 6){
       	date[2] = date[2] + 1;
       	if(date[2] >= month[date[1]] + 1){
       		date[2] = 1;
    	   }
       }
      delay(10000);
     
    }
    
    
    
    uint8 DS18B20_init()
    {
    	uint8 ans;
    	DQ = 1;
    	delay(1);
    	DQ = 0;
    	delay(100);
    	DQ = 1;
    	delay(6);
    	ans = DQ;
    	delay(100);
    	if(!ans)
    		return 1;
    	else
    		return 0;
    }
    
    void DS18B20_write(uint8 date)
    {
    	uint8 i;
    	DQ = 1;
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
    	{
    		DQ = 0;
    		if(date&0x01)  //从低到高取出数据的每位
    			DQ = 1;
    		else
    			DQ = 0;
    		delay(10);
    		DQ = 1;
    		date >>= 1;
    		delay(1);
    	}
    }
    
    uint8 DS18B20_read()
    {
    	uint8 i,date = 0;
    	DQ = 1;  //释放总线
    	delay(1);
    	for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
    	{
    		DQ = 0;
    		date >>= 1;
    		DQ = 1;
    		if(DQ)
    			date |= 0x80;  //将data的一位置1
    		delay(8);
    		DQ = 1;
    		delay(1);
    	}
    	return date;  //返回读出的数
    }
    
    void DS18B20_check()
    {
    	uint8 date1,date2;
    	float ta;
    	if(DS18B20_init())
    	{
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0x44);  //启动温度转换
    		DS18B20_init();  //复位
    		DS18B20_write(0xcc);  //跳过序列号
    		DS18B20_write(0xbe);  //启动读取温度
    		date1 = DS18B20_read();  //读取两个温度字节
    		date2 = DS18B20_read();
    		tmp = date2;
    		tmp <<= 8;
    		tmp = tmp|date1;
    		ta = tmp*0.0625;
    		tmp = ta*1000;
    	}
    }
    
    
    void dispaly_3(){//显示温度 
       temp[2] = 0x30 + tmp / 10000;
       temp[3] = 0x30 + tmp / 1000 % 10;
        write_com(0x8c);//起点为第一行第十一个字符 
     
         write_date(temp[0]);
          delay(1);	
          write_date(temp[1]);
          delay(1);
    	   write_date(temp[2]);
          delay(1);
    	   write_date(temp[3]);
          delay(1);
       write_com(0x02);
    }
     
    
    void main()
    {
    	
      DS18B20_init();  //DS18B20初始化
      DS18B20_write(0xcc);  //跳过序列号
      DS18B20_write(0x44);  //启动温度转换
     intpt_begin();//开中断 
      init();
      while(1){
       month_change(); 
       dispaly_1();
       DS18B20_check();  //从DS18B20中读取温度
       dispaly_3();
       dispaly_2();
       key =  getKey();//扫描键盘 
       if(key != -1) key_control();
     }
    }
    

    ——— 2023.5.23


    总结:

    本代码不足之处还是有的,即采用中断函数测量一秒,不准确。更改方法就是用实验板自带芯片测时间会更准确。

    —— 2023.5.23


    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于单片机实验板的液晶屏显示时间、日期、温度并支持按键控制

    发表评论