51单片机lcd1602显示时间日期

实验内容:
      使用51单片机控制LCD1602液晶显示屏显示 时间/日期/星期/温度 信息,并可通过按键设置值。

仿真效果展示:
在这里插入图片描述
proteus仿真图:
在这里插入图片描述

硬件测试图:
在这里插入图片描述
说明:
硬件测试按键使用左侧的四个独立按键
key1-设置键(选设置位)
key2:加一
key3:减一
key4:切换到日期/时间


主要硬件:

  1. AT89C51主控芯片
  2. LM016L/LCD1602 液晶显示模块
  3. RESPACK-8 排阻
  4. DS18B20 温度传感器
  5. BUTTON 按键

注:LM016L和LCD1602 原理是一样的,用法也相同。只是protues中lm0161没有显示调节亮度的那两个端口


对比
在这里插入图片描述
此次代码采用模块化的方式,硬件初始化和相关代码单独封装在一个文件中,使用时将其包含就好。


项目结构如图:
在这里插入图片描述


列出几个比较重要的函数:
主函数:

#include <reg52.h>
#include "LM016L.h"
#include "Timer.h"
#include "Data.h"
#include "Button.h"
#include "temp.h"

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数 程序入口
* 参数			 :无
*******************************************************************************/
void main()
{
	LcdInitiate();	//液晶屏初始化
	TimerInit();   	//定时器初始化
//	Ds18b20Init();	//温度传感器不在这里初始化,在每次温度转化时和读取温度时都要初始化
	while(1)
	{
		 KeyScan();				//按键检测
		 button_setting();		//按键 设置处理
		 button_up_down();		//按键 加一/减一 处理
		 ButtonSwitchDT();		//按键 切换时间/日期 处理

		 //想显示哪个就显示哪个,不想要的可以注释掉
		 TimerShow();			//时间显示	 星期显示在时间里
		 DataShow();			//日期显示
		 Lcd_Tem_Display(Ds18b20ReadTemp());	//温度显示
	}	
}

定时器中断函数:

/*******************************************************************************
* 函 数 名         : Timer0()
* 函数功能		   : 定时器0中断函数
* 参数			   :无
*******************************************************************************/		
void Timer0() interrupt 1
{
	 TH0=0x4C;
	 TL0=0x00;
	 i++;

	//使得setting_flag 0.2秒转换一次
	if(i%10<5)
	{
		blink_flag = 0;
	}
	if(i%10>=5)
	{
		blink_flag = 1;
	}

	 if(i==20)//20个50毫秒即一秒
		{
			i=0;
		   if(button_num1==0)
		   {
		   	   num1++;
		   }
			if(num1==60)
			{
				num1=0;
				num2++;
				if(num2==60)//定时一小时自动清零
				{
					num2=0;
					num3++;
					if(num3==24)
					{
						num3=0;
						day++; 		//一天过去星期加一	
						weekday++;
						if(weekday==8)
						{
							weekday=1;
						}
						//日期处理
						DataDeal1();	//一天过去年月日相应变化
					}
				}	
			}
		}		
}


/*******************************************************************************
* 函 数 名       : DataDeal1
* 函数功能		 : 日期处理函数,计算日期的当前的日期值
* 参数			 :无
*******************************************************************************/
void DataDeal1()
{

	if(day>=30)		//默认一个月30天
	{
		month++;
		day=1;

		if(month>=13)
		{
			month = 1;
			year2++;
			if(year2>=100)
			{
				year2 = 0;	//由于年数太大后int型变量无法存储,使用两个变量存储高两位和低两位
				year1++;
				if(year1>=100)
				{
					year1=0;
				}
			}
		}			
	}
}

按键处理函数:

/***********************************************************
*函数名		:KeyScan
*功能		: 按键扫描,返回按下的按键对应的位,并防止连按
*返回值		:返回按键按下的位置
*参数		:无
************************************************************/
char KeyScan() 
{
	static unsigned char klast = 0;	  //记录上一次的按键值
	unsigned char trg = 0,key = 0;		  //trg:得到的返回值,返回值中8位只有一位为1,为1的位代表按下的位,其余位为零
	key = P2 & 0xF0;				  //将按下的位转换为0 没按下的位依然为1
	key ^= 0xF0;					  //异或之后没按下的位转换为1,按下的位转换为0
	trg = key & (key ^ klast);		  //这句是最关键的一句,需要自己理解
	klast = key;

	button_flag = trg;

	return trg;	  						//最终返回值是按下哪个按键,返回值对应就是1,没按对应的就是0  eg:按下button3 则返回0x01 0000 0100
}

温度传感器初始化函数:

/*******************************************************************************
* 函数名         : Ds18b20Init
* 函数功能		   : 初始化
* 输入           : 无
* 输出         	 : 初始化成功返回1,失败返回0
*******************************************************************************/
unsigned char Ds18b20Init()
{
	unsigned int i;
	DSPORT=0;			 //将总线拉低480us~960us
	i=70;	
	while(i--);//延时642us
	DSPORT=1;			//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
	i=0;
	while(DSPORT)	//等待DS18B20拉低总线
	{
		i++;
		if(i>5000)//等待>5MS
			return 0;//初始化失败	
	}
	return 1;//初始化成功
}

这里需要注意的一点是,温度传感器并不需要一直转换温度,读取温度。而是在需要温度的时候再去初始化一下(转化和读取时),如果只在最开始初始化,转化时没有初始化则无法读取温度值。具体请看项目源码。

完整项目下载地址:
[仿真版源码] (https://github.com/Little-Water-Bottle/LCD1602ShowDataAndTime)
(补充链接:仿真版源码 密码:7jdc)

51普中开发板源码 密码:aeg3

proteus文件下载 密码:guqw

参考资料下载(!):
LCD和DS18B20参考资料 密码:64l7

排版真的是垃圾,算了记录一下就行了。。

  • 56
    点赞
  • 469
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
好的,下面是一个简单的51单片机LCD1602显示日期的程序的实现。 首先,你需要包含头文件和定义相关的常量和函数,如下所示: ```c #include <reg52.h> // 51单片机头文件 #define LCD_RS P1_0 // LCD1602的RS引脚连接到P1.0 #define LCD_RW P1_1 // LCD1602的RW引脚连接到P1.1 #define LCD_EN P1_2 // LCD1602的EN引脚连接到P1.2 #define LCD_D4 P1_4 // LCD1602的D4引脚连接到P1.4 #define LCD_D5 P1_5 // LCD1602的D5引脚连接到P1.5 #define LCD_D6 P1_6 // LCD1602的D6引脚连接到P1.6 #define LCD_D7 P1_7 // LCD1602的D7引脚连接到P1.7 void LCD_Init(void); void LCD_WriteCommand(unsigned char command); void LCD_WriteData(unsigned char data); void LCD_WriteString(unsigned char *string); void LCD_SetCursor(unsigned char row, unsigned char col); void LCD_Clear(void); void LCD_ShowDate(void); ``` 其中,LCD_Init函数用于初始化LCD1602LCD_WriteCommand函数用于向LCD1602写入命令,LCD_WriteData函数用于向LCD1602写入数据,LCD_WriteString函数用于向LCD1602写入字符串,LCD_SetCursor函数用于设置LCD1602的光标位置,LCD_Clear函数用于清除LCD1602显示内容,LCD_ShowDate函数用于显示当前日期。 然后,你需要编写相应的函数来实现LCD1602的初始化、写命令、写数据、写字符串、设置光标位置以及清除显示内容等功能。这里我提供一个与前面稍微不同的参考实现,如下所示: ```c // 初始化LCD1602 void LCD_Init(void) { LCD_WriteCommand(0x02); // 光标复位 LCD_WriteCommand(0x0c); // 显示开,光标关闭,闪烁关闭 LCD_WriteCommand(0x06); // 光标右移,文字不动 LCD_Clear(); // 清除显示内容 } // 向LCD1602写入命令 void LCD_WriteCommand(unsigned char command) { LCD_RS = 0; // RS引脚为低电平,表示写入命令 LCD_RW = 0; // RW引脚为低电平,表示写入操作 LCD_EN = 1; // EN引脚为高电平,表示操作开始 LCD_D7 = (command >> 7) & 0x01; // 最高位 LCD_D6 = (command >> 6) & 0x01; LCD_D5 = (command >> 5) & 0x01; LCD_D4 = (command >> 4) & 0x01; LCD_EN = 0; // EN引脚为低电平,表示操作结束 LCD_EN = 1; // EN引脚为高电平,表示操作开始 LCD_D7 = (command >> 3) & 0x01; // 次高位 LCD_D6 = (command >> 2) & 0x01; LCD_D5 = (command >> 1) & 0x01; LCD_D4 = command & 0x01; LCD_EN = 0; // EN引脚为低电平,表示操作结束 } // 向LCD1602写入数据 void LCD_WriteData(unsigned char data) { LCD_RS = 1; // RS引脚为高电平,表示写入数据 LCD_RW = 0; // RW引脚为低电平,表示写入操作 LCD_EN = 1; // EN引脚为高电平,表示操作开始 LCD_D7 = (data >> 7) & 0x01; // 最高位 LCD_D6 = (data >> 6) & 0x01; LCD_D5 = (data >> 5) & 0x01; LCD_D4 = (data >> 4) & 0x01; LCD_EN = 0; // EN引脚为低电平,表示操作结束 LCD_EN = 1; // EN引脚为高电平,表示操作开始 LCD_D7 = (data >> 3) & 0x01; // 次高位 LCD_D6 = (data >> 2) & 0x01; LCD_D5 = (data >> 1) & 0x01; LCD_D4 = data & 0x01; LCD_EN = 0; // EN引脚为低电平,表示操作结束 } // 向LCD1602写入字符串 void LCD_WriteString(unsigned char *string) { while (*string != '\0') { LCD_WriteData(*string); string++; } } // 设置LCD1602的光标位置 void LCD_SetCursor(unsigned char row, unsigned char col) { unsigned char address; if (row == 0) { address = 0x80 + col; } else if (row == 1) { address = 0xc0 + col; } else { return; } LCD_WriteCommand(address); } // 清除LCD1602显示内容 void LCD_Clear(void) { LCD_WriteCommand(0x01); LCD_SetCursor(0, 0); } // 显示当前日期 void LCD_ShowDate(void) { unsigned char year, month, day; // TODO: 获取当前日期的代码 LCD_SetCursor(0, 0); LCD_WriteString("Date:"); LCD_WriteData('0' + year / 10); LCD_WriteData('0' + year % 10); LCD_WriteData('/'); LCD_WriteData('0' + month / 10); LCD_WriteData('0' + month % 10); LCD_WriteData('/'); LCD_WriteData('0' + day / 10); LCD_WriteData('0' + day % 10); } ``` 其中,LCD_Init函数用于初始化LCD1602LCD_WriteCommand函数用于向LCD1602写入命令,LCD_WriteData函数用于向LCD1602写入数据,LCD_WriteString函数用于向LCD1602写入字符串,LCD_SetCursor函数用于设置LCD1602的光标位置,LCD_Clear函数用于清除LCD1602显示内容,LCD_ShowDate函数用于显示当前日期。 最后,你可以在主函数中调用LCD_ShowDate函数来显示当前日期。例如,你可以编写一个简单的程序来显示当前日期,如下所示: ```c void main(void) { LCD_Init(); // 初始化LCD1602 LCD_ShowDate(); // 在LCD1602显示当前日期 while (1); // 程序运行结束 } ``` 希望这个程序能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值