项目15—温度计与电子表用LCD1602显示

所作的仿真图如下:

程序分为五个部分

程序如下:

main.c

#include<reg51.h>
unsigned char cp,cp2,flash,sec,min,hour,day,month,i,t_x1;
int cp1;
unsigned int year = 2021;
#include<lcd1602.c>	 
#include<ds18b20.c>
#include<display.c>	 
#include<ds1302.c> 
void timer_isr(void) interrupt 1
{
	TH0 = (65535 - 2000) / 256;
	TL0 = (65535 - 2000) % 256;
	cp++;cp2++;
	if(cp >= 250)
	{
		cp = 0;
		flash++;	
	}								
	if(flash >= 2){flash = 0;sec++;}			
	if(sec >= 60){min++;sec = 0;}
	if(min >= 60){min = 0;hour++;}
	if(hour >= 24){hour = 0;day++;}
	if(day > 31){day = 1;month++;}
	if(month > 12){year++;month = 1;}
	if(cp2 >= 250)
	{
		cp2 = 0;
		display0();
		display1();
		display2();		
	}
}
void timer_init(void)
{
	TMOD = 0x01;
	TH0 = (65535 - 2000) / 256;
	TL0 = (65535 - 2000) % 256;
	EA = 1;
	ET0 = 1;
	TR0 = 1;
}
void main(void)
{
	timer_init();  
//	write_init_time();
	get_ds1302();	   
	lcd1602_init();
	lcd1602_clear();
	while(1)
	{
	  	display3();
		cp1++;
		if(cp1 >= 1000)
		{
		 	cp1 = 0;
			get_ds18b20();	
			if((t_x & 0x80) == 0x80)
			{
			 	t_x1 = 0xff - t_x;
				t_d = (0x0f - t_d)*0.625 + 1;
				if(t_d == 10){t_x1 = t_x1 + 1;t_d = 0;}
			}
			else {t_x1 = t_x;t_d = t_d*0.625;
			}
			}
	}
}

 dispaly.c

void display0()
{
	goto_xy(1,0);
	display_string("Time:"); 
	display_num(hour / 10);
	display_num(hour % 10); 
//	display_num(hour);
	if(flash)display_string("-");	 
	else display_string(" ");
	display_num(min / 10);
	display_num(min % 10); 
//	display_num(min);
	if(flash)display_string("-");
	else display_string(" ");		
	display_num(sec / 10);
	display_num(sec % 10);
//	display_num(sec);
	goto_xy(2,0);
	display_string("Temp:"); 
//	display_num(year / 1000);
//	display_num(year / 100 % 10);
	display_num(t_x1 / 10 % 10);
	display_num(t_x1 % 10);		 
//	if(flash)display_string("-");
//	else display_string(" ");
//	display_num(mon / 10);
//	display_num(mon % 10); 
//	if(flash)display_string("-");
//	else display_string(" ");		
//	display_num(day / 10);
//	display_num(day % 10);	
}
unsigned char smg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
char k;
void display1(void)	  		
{
	P0 = 0xff;
	switch(k)
	{
		case 0:P1 = 0x01;P0 = smg[sec % 10];break;
		case 1:P1 = 0x02;P0 = smg[sec / 10];break;
		case 2:P1 = 0x04;P0 = 0xbf | flash;break;
		case 3:P1 = 0x08;P0 = smg[min % 10];break;
		case 4:P1 = 0x10;P0 = smg[min / 10];break;
		case 5:P1 = 0x20;P0 = 0xbf | flash;break;
		case 6:P1 = 0x40;P0 = smg[hour % 10];break;
		case 7:P1 = 0x80;P0 = smg[hour / 10];break;
	}
	k++;
	if(k>=8)k = 0;
}
void display2(void)	 	  
{
	P0 = 0xff;
	switch(k)
	{
		case 0:P1 = 0x01;P0 = smg[day % 10];break;
		case 1:P1 = 0x02;P0 = smg[day / 10];break;
		case 2:P1 = 0x04;P0 = 0xbf;break;
		case 3:P1 = 0x08;P0 = smg[month % 10];break;
		case 4:P1 = 0x10;P0 = smg[month / 10];break;
		case 5:P1 = 0x20;P0 = 0xbf;break;
		case 6:P1 = 0x40;P0 = smg[year % 10];break;
		case 7:P1 = 0x80;P0 = smg[year / 10];break;
	}
	k++;
	if(k>=8)k = 0;
}
void display3(void)
{
	P0 = 0xff;
	switch(i)
	{
		case 0:P2 = 0x01;P0 = 0xff;break;
		case 1:P2 = 0x02;if((t_x & 0x80) == 0x80)P0 = 0xbf;else P0 = 0xff;break;
		case 2:P2 = 0x04;if(t_x1 < 10)P0 = 0xff;else P0 = smg[t_x1 / 10];break;
		case 3:P2 = 0x08;P0 = smg[t_x1 % 10] & 0x7f;break;
		case 4:P2 = 0x10;P0 = smg[t_d];break;
		case 5:P2 = 0x20;P0 = 0xc6;break;
	}
	i++;
	if(i >= 6)i = 0;
}

LCD1602.C

#define uchar unsigned char 
#define uint  unsigned int
sbit RS = P2^4;//数据/命令
sbit RW = P2^5;//读/写
sbit E  = P2^6;//使能
uchar i;
void delay(unsigned int x)
{
	while(x--);
}
void write_command(uchar command)
{
	RW = 0;
	RS = 0;
	P0 = command;
	E = 1;
	delay(100);
	E = 0;
	RW = 1;
}
void write_data(uchar date)
{
	RW = 0;
	RS = 1;
	E = 1;
	P0 = date;
	delay(100);
	E = 0;
	RW = 1;
}
void lcd1602_init(void)
{
	write_command(0x38);
	write_command(0x0f);	
	write_command(0x0c);	
	write_command(0x06);
}
void lcd1602_clear(void)
{
	write_command(0x01);
	write_command(0x02);
}
void display_string(uchar *p)
{
	while(*p)
	{
		write_data(*p);
		p++;	
	}
}
void display_num(uchar x)
{
双数字
//	write_data((x / 10) + 0x30);
//	write_data((x % 10) + 0x30);
//单数字
	write_data(x + 0x30);
}
void goto_xy(uchar x,uchar y)
{
	if(x == 1)
	write_command(0x80 + y);
	if(x == 2)
	write_command(0x80 + 0x40 + y);
}

 DS1302.C

sbit CE = P3^5;
sbit SCLK = P3^6;
sbit IO = P3^7;
unsigned char week;
void ds1302_init()//初始化
{
	CE = 0;
	SCLK = 0;
	CE = 1;    //允许读写数据
}
/*对ds1302写一字节数据*/
void write_ds1302_onebyte(unsigned char dat)
{
	unsigned char i;
	for(i = 0;i < 8;i++)
	{
		SCLK = 0;
		IO = (bit)(dat & 0x01);  // 0001 & 0001 //把写入的数据取出来给DS1302
		SCLK = 1;
		dat = dat >> 1; //每取一次 移一位 
	}
}	
/*从DS1302里面读出一字节数据*/
unsigned char read_ds1302_onebyte()
{
	unsigned char i,j;
	for(i = 0;i<8;i++)
	{
		SCLK = 1;
		SCLK = 0;
		j = j >> 1; //移位
		if(IO)j = j | 0X80;  //一位一位的读取数据
	}
	return(j);//8421BCD码
}
///*对DS1302某一地址写数据*/
//void write_ds1302_add_dat(unsigned char add,unsigned char dat)
//{
//	ds1302_init();
//	write_ds1302_onebyte(add);
//	write_ds1302_onebyte(dat);
//	CE = 0; //关闭CE不再读写数据 IO SCLK 变为高阻态(断路)
//}
/*从DS1302里面读出数据*/
unsigned char read_ds1302_add(unsigned char add)
{
	unsigned char dat_temp;
	ds1302_init();
	write_ds1302_onebyte(add);
	dat_temp = read_ds1302_onebyte();
	CE = 0;
	return(dat_temp);
}
/*8421BCD码转十进制*/
unsigned char BCD_DEC(unsigned char x)
{	
	unsigned char dec;
	dec = x & 0x0f; //取出低四位
	x = x >> 4; //挤出低四位,把高四位放到地位
	dec = x*10 + dec;
	return(dec);
}
///*十进制转8421BCD码*/
//unsigned char DEC_BCD(unsigned char x)
//{
//	unsigned char bcd;
//	bcd = x % 10;//取出十进制的个位
//	x = x / 10;//取出十进制的十位
//	x = x << 4;
//	bcd = bcd | x;
//	return(bcd);
//}
///*单片机向DS1302里面写数据*/
//void write_init_time()
//{
//	write_ds1302_add_dat(0x8e,0x00);//关闭保护
//	write_ds1302_add_dat(0x80,DEC_BCD(sec));//写秒
//	write_ds1302_add_dat(0x82,DEC_BCD(min));//写分
//	write_ds1302_add_dat(0x84,DEC_BCD(hour));//写时
//	write_ds1302_add_dat(0x86,DEC_BCD(day));//写日
//	write_ds1302_add_dat(0x88,DEC_BCD(month));//写月
//	write_ds1302_add_dat(0x8A,DEC_BCD(week));//写周
//	write_ds1302_add_dat(0x8C,DEC_BCD(year));//写年
//	write_ds1302_add_dat(0x8e,0x10);//打开保护
//}
/*单片机从DS1302里面得到时间数据*/
void get_ds1302()
{
	unsigned char R;
	R = read_ds1302_add(0x81);//读秒
	sec = BCD_DEC(R);
	R = read_ds1302_add(0x83);//读分
	min = BCD_DEC(R);
	R = read_ds1302_add(0x85);//读时
	hour = BCD_DEC(R);
	R = read_ds1302_add(0x87);//读日
	day = BCD_DEC(R);
	R = read_ds1302_add(0x89);//读月
	month = BCD_DEC(R);
	R = read_ds1302_add(0x8B);//读周
	week = BCD_DEC(R);
	R = read_ds1302_add(0x8D);//读年
	year = BCD_DEC(R);
}

DS18B20.C

unsigned char t_x,t_d;
sbit dq = P1^7;
//void delay(unsigned int x){while(x--);}				//延迟函数
/*初始化*/
void ds18b20_init(void)								//初始化函数
{
 	unsigned char x = 255;
	dq = 1;											//先让dq置1
	dq = 0;											//单片机将dq拉低
	delay(80);										//延时480~960us
	dq = 1;										   	//释放总线
	delay(5);										
	while(dq && x--);								//等待返回低电平响应,若无响应,则做适量延时后往下进行
	delay(20);
}
/*向DS18B20中写一个字节*/
void write_ds18b20(unsigned char x)					//写一个字节函数
{
 	unsigned char i;
	for(i = 0;i < 8;i++)
	{
	 	dq = 0;										//发送起始信号
		dq = (bit)(x & 0x01);						//取x最低位
		x = x >> 1;									//x依次向右移动一位
		delay(10);									//延迟约45us
		dq = 1;										//释放总线
	}
	dq = 1;											//将数据线拉高
}
/*从DS18B20中读一个字节*/
unsigned char read_ds18b20(void)					//读一个字节函数
{
 	unsigned char i,j;
	for(i = 0;i < 8;i++)
	{
	 	dq = 0;										//发送启动信号
		delay(1);									//延时6us
		dq = 1;										//释放总线
		j = j>>1;									//j右移一位
		if(dq)j |= 0x80;							//如果是高电平,则把j的最高位置1,如果不是,默认值0
		delay(5);									//延时40us
		dq = 1;										//释放总线
	}
	dq = 1;
	return(j);
}
/*读取温度*/
void get_ds18b20(void)				//读取温度函数
{
 	unsigned char i;
	ds18b20_init();				   	//初始化
	write_ds18b20(0xcc);		   	//跳过读序列号操作
	write_ds18b20(0x44);		   	//启动温度转换	
	ds18b20_init();					//初始化
	write_ds18b20(0xcc);		  	//跳过读序列号操作
	write_ds18b20(0xbe);		 	//读取温度寄存器
	t_x = read_ds18b20();		 	 //读取温度低位
	i = read_ds18b20();				 //读取温度高位
	t_d	= t_x & 0x0f;			 	//读取小数部分			 	
	t_x	= (i << 4) | (t_x >> 4); 	//低位右移四位,高位左移四位
}

 实现结果如下:

 

 

 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单旦羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值