单片机期末设计 - 液晶显示屏显示时间、日期、温度及按键控制(实验板实现)

这篇具有很好参考价值的文章主要介绍了单片机期末设计 - 液晶显示屏显示时间、日期、温度及按键控制(实验板实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:


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


本代码涉及的主要知识:


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文章来源地址https://www.toymoban.com/news/detail-474820.html


到了这里,关于单片机期末设计 - 液晶显示屏显示时间、日期、温度及按键控制(实验板实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32单片机LED显示屏驱动原理与实现

    STM32单片机驱动LED显示屏的原理与实现方法与Arduino类似,但涉及到的具体硬件资源和库函数可能会有所不同。下面是一个详细的介绍:   原理: STM32单片机驱动LED显示屏的原理是通过控制GPIO引脚的电平状态来控制LED的亮灭。通过设置引脚的输出电平为高电平(VCC)或低电平

    2024年02月10日
    浏览(51)
  • 51单片机 | LCD1602 液晶显示实验

      在前面章节,我们已经学习过几种显示装置,例如静态数码管、动态数码管、 8*8LED 点阵、串口通信。使用它们可以直观显示一些字符数据,但是它们也有各种局限性,比如显示字符数据太少,硬件设计复杂、代码编写难度大等。这一章就来介绍一种非常简单且常用的显

    2023年04月11日
    浏览(65)
  • 单片机设计:stm32远程水位检测灌溉系统(水泵+电机驱动+OLED显示屏+水位传感器+防水式ds18b20+光敏传感器+按键+WiFi+手机app)

    单片机设计:stm32远程水位检测灌溉系统(水泵+电机驱动+OLED显示屏+水位传感器+防水式ds18b20+光敏传感器+按键+WiFi+手机app) 一、主要功能:    1.水位传感器检测水的高度、光敏传感器检测周围光照强度、ds18b20检测水温 2.0LED、手机app显示当前数据以及阈值 3.手机app远程调节阈值,

    2024年02月05日
    浏览(50)
  • 51单片机LCD1602液晶屏显示方法

    以显示hello,world!    2022.10.17  为例。 首先把LCD1602的模块化程序添加到项目目录中,模块化方法在51单片机之程序模块化_学习笔记吧的博客-CSDN博客这里可以学习。 实验程序: LCD1602.c文件代码: LCD1602.h文件代码: 把这两个代码,分别添加到LCD1602.c 和 LCD1602.h 文件,然后添加

    2023年04月08日
    浏览(55)
  • 基于单片机的点阵电子显示屏上下左右移加减速系统

    一、系统方案 本设计的任务就是完成一个16 16的点阵设计,并能滚动显示“ ********************”内容。 主要内容是,能同时流动显示汉字;能实现显示汉字无闪烁;能实屏幕亮度较高。本LED显示屏能够以动态扫描的方式显示一个16×16点阵汉字,并能通过单片机实现内容滚动显示

    2024年02月09日
    浏览(41)
  • STC89C52单片机LCD1602显示屏介绍与代码演示

    LCD1602显示屏介绍 引脚介绍 内部结构框图  存储器  DDRAM储存器地址  CGRAM与 CGROM的地址 时序介绍 LCD1602快捷指令  LCD1602指令操作流程: 字符、字符串的显示  各种进制的数字显示 在LCD1602上显示十进制数字 在LCD1602上显示十六进制数字 在LCD1602上显示二进制数字 LCD1602(Liq

    2024年02月08日
    浏览(51)
  • 单片机 用LCD显示屏 输出字符串源代码(附Proteus图)

    附:字符型LCD显示屏型号:LM016L;这个代码应该是可以直接运行的

    2024年02月14日
    浏览(39)
  • 【51单片机】LCD1602 液晶显示实验指导书

             来介绍一种非常简单且常用的显示装置——LCD1602 液晶显示器,使用它可以显示更多的字符数字。这将有助于我们清晰的观察程序的运行结果,更加方便我们的后续调试和开发。         我们的开发板上集成了一个 LCD1602 液晶显示器接口,将LCD1602 液晶对应插

    2024年02月01日
    浏览(63)
  • 单片机C语言实例:18、LCD1602液晶显示

    学单片机的小朋友应该都见过这个显示器--LCD1602,这是最古老最简单的显示屏,上世纪80年代的产物。 它显示的图案如下所示 显示部分放大就是下面这样 ,像素就是一个个小方块,相当于描点法绘图了。 如果把所有像素全部显示出来就是下面这样,全部是小黑点  全部点亮

    2024年02月09日
    浏览(49)
  • 【附报告】51单片机计算器(LCD1602液晶显示)

      由于本文较早,这里推荐一下近期刚优化的:【优化】51单片机计算器(LCD1602液晶显示)_Gxtoeilee的博客-CSDN博客   1 设计目标 设计可选模式的计算器  2 主要功能 功能一:可选两种计算模式,模式一为四则运算,模式二为扩展内容; 功能二:除法的计算结果保留到小数点

    2024年02月11日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包