龙空技术网

51单片机项目设计:基于51单片机时钟万年历(含代码、原理图)

嵌入式xff 238

前言:

目前小伙伴们对“万年历数据库源码”大约比较关切,你们都想要了解一些“万年历数据库源码”的相关知识。那么小编在网摘上网罗了一些对于“万年历数据库源码””的相关知识,希望大家能喜欢,看官们一起来了解一下吧!

大家好,今天给大家介绍基于单片机stm32的多功能氛围灯、手机控制ws2812和MCU升级程序,文章末尾附有本毕业设计的论文和源码的获取方式,也可现在直接进群免费领取。

点击这里找小助理0元领取:扫码进群领资料

一、项目功能

1、可以显示当前时间、星期、日期

2、可以修改当前时间、星期、日期

3、可以获取环境的温度,并显示到LCD

4、可以设置闹钟,当时间到蜂鸣器鸣叫、按下按键后关闭鸣叫

二、材料选择

(一)主控选择:STC89C52RC

STC89C52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。

(二)显示屏选择:LCD1602

LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能有所不同,但使用方法都是一样的。为了降低成本,绝大多数制造商都直接将裸片做到板子上。

(三)时钟芯片选择:DS1302

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。

(四)温度传感器选择:DS18B20

DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。 [1] DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。

(五)外围器件:按键、蜂鸣器、开关、纽扣电池、电位器、三极管等

三、原理图设计

(一)最小系统

供电、晶振、复位电路

(二)显示屏电路

数据线接到P0,注意要接1K上拉电阻

四、PCB设计

五、程序设计

/***************************************************************************************项目:51单片机时钟万年历设计*作者:化作尘*版本:V1.1*邮箱:2809786963@qq.com*时间:2020年12月1日16:43:51	*哔哩哔哩视频地址:*注意事项:闹钟根据实物设计,不能仿真,使用的是内部eeprom***************************************************************************************/#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器#include "ds1302.h"#include "temp.h"#include "lcd.h"#include "eeprom.h"sbit k1 = P1^0;	  		//按键sbit k2 = P1^1;			 sbit k3 = P1^2;sbit k4 = P1^3;sbit lcdled = P2^4;	 		 //lcd背光sbit beep = P1^4;			//蜂鸣器unsigned int ti=0,alarm=0;       //修改第几个时间参数 、修改第几个闹钟参数unsigned char alarm_hour=0x12,alarm_min=0x00;	 //闹钟时、分参数enum Mode				//定义枚举、三种模式{	DISPLAYDATA,MODIFYDATA,SETALARMCLOCK,NONE,ALARMCLOCK}mode;enum Alarmswitch	 //定义闹钟开关{	OFF,ON}alarmswitch;/*********延时函数***********/		  void delay(unsigned int t)	 //短延时{ 	while(t--);}void delay_ms(unsigned int t)	//毫秒延时{	unsigned int a,b;	for(a=0;a<t;a++)	for(b=0;b<120;b++);}/********显示日期、时间、星期***********/void display_data(void){	LcdWriteCom(0x80);	LcdWritestr("20");		LcdWriteData(TIME[6]/16+0x30);	  //年	LcdWriteData(TIME[6]%16+0x30);	LcdWriteData('-');	LcdWriteData(TIME[4]/16+0x30);	  //月	LcdWriteData(TIME[4]%16+0x30);	LcdWriteData('-');	LcdWriteData(TIME[3]/16+0x30);	  //日	LcdWriteData(TIME[3]%16+0x30);	LcdWritestr("  ");	switch(TIME[5])					   //显示星期	{				case 0:LcdWritestr("Mon"); break;		case 1:LcdWritestr("Tue"); break;		case 2:LcdWritestr("Wed"); break;		case 3:LcdWritestr("Thu"); break;		case 4:LcdWritestr("Fri"); break;		case 5:LcdWritestr("Sat"); break;		case 6:LcdWritestr("Sun"); break;	}	if(alarmswitch==ON)LcdWriteData('.');	else LcdWriteData(' ');	LcdWriteCom(0xC0);	LcdWriteData(' ');	LcdWriteData(TIME[2]/16+0x30);	  //时	LcdWriteData(TIME[2]%16+0x30);	LcdWriteData(':');	LcdWriteData(TIME[1]/16+0x30);	  //分	LcdWriteData(TIME[1]%16+0x30);	LcdWriteData(':');	LcdWriteData(TIME[0]/16+0x30);	  //秒	LcdWriteData(TIME[0]%16+0x30);	LcdWritestr(" ");}/*********显示温度***********/void displaytemp(int temp) 	 //显示温度{   	float tp;  	static char flag = 1;	if(temp< 0)			  	{		LcdWriteCom(0xca);		LcdWriteData('-'); 		temp=temp-1;		temp=~temp;		tp=temp;		temp=tp*0.0625*100+0.5;	   	} 	else  	{					LcdWriteCom(0xca);		LcdWriteData('+'); 		tp=temp;		temp=tp*0.0625*100+0.5;		}		if(flag)		{			flag =0;			temp = 2600;		}	if(temp==8500)		return ;	LcdWriteData(temp % 10000 / 1000 + 0x30);	LcdWriteData(temp % 1000 / 100  + 0x30);	LcdWriteData('.');	LcdWriteData(temp % 100 / 10 + 0x30);	LcdWriteData(temp % 10 + 0x30);}/******************************************************************************** 函 数 名         : keypros* 函数功能		   : 按键处理函数,判断按键K1是否按下*******************************************************************************/void keypros()		   //初始页面按键检测{	if(k1 == 0)			   //切换模式	{		delay(1000);   //消除抖动 一般大约10ms		if(k1==0)	 //再次判断按键是否按下		{			mode+= 1;if(mode == 3)mode = DISPLAYDATA;		}		while(k1 == 0);	}	else if(k2 == 0)			  //蜂鸣器测试	{		delay(1000);   //消除抖动 一般大约10ms		if(k2==0)	 //再次判断按键是否按下		{			beep = !beep;  		}		while(k2 == 0);	}	else if(k3 == 0)		   //背光灯测试	{		delay(1000);   //消除抖动 一般大约10ms		if(k3==0)	 //再次判断按键是否按下		{			lcdled = !lcdled;  		}		while(k3 == 0);	}	else if(k4 == 0)			//背光灯测试	{		delay(1000);   //消除抖动 一般大约10ms		if(k4==0)	 //再次判断按键是否按下		{			alarmswitch=!alarmswitch;  		}		while(k4 == 0);	}		}/*************修改时间************/void modify(void){	static int time=0;	time++;	if(k1 == 0)			//切换模式	{		delay(1000);   //消除抖动 一般大约10ms		if(k1==0)	 //再次判断按键是否按下		{			mode+= 1;if(mode == 3)mode = DISPLAYDATA;		}		while(k1 == 0);	}	else if(k2 == 0)		   //选择修改参数	{		delay(1000);   //消除抖动 一般大约10ms		if(k2==0)	 //再次判断按键是否按下		{			ti++; 			if(ti == 8)ti=0; 		}		while(k2 == 0);	}	else if(k3 == 0 ||k4 == 0)	switch(ti)				   //选择进入修改参数	{		case 0:						if(k4==0 | k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4==0 | k3 ==0)	 //再次判断按键是否按下							{							   TIME[0]=0;							}							while(k4 == 0 | k3==0);						}												break;    //?		case 1:						if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[1]++;							   if(TIME[1]%16 == 0x0a)							   {							   		TIME[1] += 16;									TIME[1] &= 0xf0;							   }if(TIME[1]==0x60)TIME[1]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[1]--;							   if(TIME[1]%16==0x0f && TIME[1]!=0xff)							   {									TIME[1] &= 0xf9;							   }							   if(TIME[1]==0xff)TIME[1]=0x59;							}							while(k4==0);						}						break;    //?		case 2:						if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[2]++;							   if(TIME[2]%16 == 0x0a)							   {							   		TIME[2] += 16;									TIME[2] &= 0xf0;							   }if(TIME[2]==0x24)TIME[2]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[2]--;							   if(TIME[2]%16==0x0f && TIME[2]!=0xff)							   {									TIME[2] &= 0xf9;							   }							   if(TIME[2]==0xff)TIME[2]=0x23;							}							while(k4==0);						}						break;    //?		case 3:						if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[3]++;							   if(TIME[3]%16 == 0x0a)							   {							   		TIME[3] += 16;									TIME[3] &= 0xf0;							   }if(TIME[3]==0x32)TIME[3]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[3]--;							   if(TIME[3]%16==0x0f && TIME[3]!=0xff)							   {									TIME[3] &= 0xf9;							   }							   if(TIME[3]==0xff)TIME[3]=0x31;							}							while(k4==0);						}						break;	 //日		case 4:											if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[4]++;							   if(TIME[4]%16 == 0x0a)							   {							   		TIME[4] += 16;									TIME[4] &= 0xf0;							   }if(TIME[4]==0x13)TIME[4]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[4]--;							   if(TIME[4]%16==0x0f && TIME[4]!=0xff)							   {									TIME[4] &= 0xf9;							   }							   if(TIME[4]==0xff)TIME[4]=0x12;							}							while(k4==0);						}						break;	 //月		case 5:												if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[5]++;if(TIME[5]==7)TIME[5]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[5]--;if(TIME[5]==0xff)TIME[5]=6;							}							while(k4==0);						}						break;	 //周		case 6:												if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   TIME[6]++;							   if(TIME[6]%16 == 0x0a)							   {							   		TIME[6] += 16;									TIME[6] &= 0xf0;							   }if(TIME[6]==0xa0)TIME[6]=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   TIME[6]--;							   if(TIME[6]%16==0x0f && TIME[6]!=0xff)							   {									TIME[6] &= 0xf9;							   }							   if(TIME[6]==0xff)TIME[6]=0x99;							}							while(k4==0);						}						break;	 //年		case 7: 						if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   mode=DISPLAYDATA;							   ti=0;							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   	Ds1302Init();		  //时钟初始化								mode = DISPLAYDATA;    //返回日期								ti = 0;				//还原初始修改							}							while(k4==0);						}						break;	 //年	}	if(time == 200)	{		display_data();		if(ti == 7){						LcdWriteCom(0xca);						LcdWritestr(" <- OK");		}				}	else if(time == 400)	switch(ti)				   //选择进入修改参数	{		case 0: 						LcdWriteCom(0xc7);						LcdWritestr("  ");			break;		case 1: 												LcdWriteCom(0xc4);						LcdWritestr("  ");		break;		case 2: 						LcdWriteCom(0xc1);						LcdWritestr("  ");									break;		case 3: 						LcdWriteCom(0x88);						LcdWritestr("  ");			break;		case 4: 						LcdWriteCom(0x85);						LcdWritestr("  ");			break;		case 5: 						LcdWriteCom(0x8c);						LcdWritestr("   ");			break;		case 6: 						LcdWriteCom(0x80);						LcdWritestr("    ");		break;		case 7: 						LcdWriteCom(0xca);						LcdWritestr("      ");			break;	}else if(time>400) time=0;		delay_ms(1);	}void setalarmclock(void)	//设置闹钟模式{	static int time=0;	time++;		if(k1 == 0)			 //切换模式	{		delay(1000);   //消除抖动 一般大约10ms		if(k1==0)	 //再次判断按键是否按下		{			mode+= 1;if(mode == 3)mode = DISPLAYDATA;		}		while(k1 == 0);	}	if(k2 == 0)			 //选择闹钟修改参数	{		delay(1000);   //消除抖动 一般大约10ms		if(k2==0)	 //再次判断按键是否按下		{			alarm++; 			if(alarm == 3)alarm=0; 		}		while(k2 == 0);	}		switch(alarm)			//选择进入修改参数	{		case 0:				if(k3 == 0)			  //控制闹钟开				{					delay(1000);   //消除抖动 一般大约10ms					if(k3==0)	 //再次判断按键是否按下					{						alarmswitch = ON;						SectorErase(0x2401);						byte_write(0x2401,alarmswitch);					}					while(k3 == 0);				}				if(k4 == 0)			 //控制闹钟关闭				{					delay(1000);   //消除抖动 一般大约10ms					if(k4==0)	 //再次判断按键是否按下					{						alarmswitch = OFF;						SectorErase(0x2401);						byte_write(0x2401,alarmswitch);					}					while(k4 == 0);				}				break;		case 1:																			if(k3==0)		  //控制闹钟时针加						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   alarm_hour++;							   if(alarm_hour%16 == 0x0a)							   {							   		alarm_hour += 16;									alarm_hour &= 0xf0;							   }if(alarm_hour==0x24)alarm_hour=0;							    SectorErase(0x2601);								byte_write(0x2601,alarm_hour);							}							while(k3==0);						}						if(k4==0)			  //控制闹钟时针减						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   alarm_hour--;							   if(alarm_hour%16==0x0f && alarm_hour!=0xff)							   {									alarm_hour &= 0xf9;							   }							   if(alarm_hour==0xff)alarm_hour=0x23;							   SectorErase(0x2601);							   byte_write(0x2601,alarm_hour);							}							while(k4==0);						}				break;		case 2:										if(k3==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k3 ==0)	 //再次判断按键是否按下							{							   alarm_min++;							   if(alarm_min%16 == 0x0a)							   {							   		alarm_min += 16;									alarm_min &= 0xf0;							   }if(alarm_min==0x60)alarm_min=0;							   SectorErase(0x2201);							   byte_write(0x2201,alarm_min);							}							while(k3==0);						}						if(k4==0)						{							delay(1000);   //消除抖动 一般大约10ms							if(k4 ==0)	 //再次判断按键是否按下							{							   alarm_min--;							   if(alarm_min%16==0x0f && alarm_min!=0xff)							   {									alarm_min &= 0xf9;							   }							   if(alarm_min==0xff)alarm_min=0x59;							   SectorErase(0x2201);							   byte_write(0x2201,alarm_min);							}							while(k4==0);						}				break;	}		if(time == 200)	{		alarm_hour=byte_read(0x2601);		alarm_min=byte_read(0x2201);		alarmswitch=byte_read(0x2401);		LcdWriteCom(0x80);			 //显示		LcdWritestr("alarm clock:    ");		LcdWriteCom(0xc0); 		if(alarmswitch == OFF)LcdWritestr("  OFF    ");		else LcdWritestr("  ON     ");		LcdWriteCom(0xc9); 		LcdWriteData(alarm_hour/16+0x30);		LcdWriteData(alarm_hour%16+0x30);		LcdWriteData(':'); 		LcdWriteData(alarm_min/16+0x30);		LcdWriteData(alarm_min%16+0x30);		LcdWritestr("    ");	}	else if(time == 400)	switch(alarm)				   //选择进入修改参数	{		case 0: 				LcdWriteCom(0xc0);				LcdWritestr("      ");			break;		case 1: 				LcdWriteCom(0xc9);				LcdWritestr("  ");		break;		case 2: 				LcdWriteCom(0xcc);				LcdWritestr("  ");									break;			}else if(time>400) time=0;					delay_ms(1);}/************闹钟模式*****************/void alarmclock(void){    if(alarmswitch==ON && alarm_hour==TIME[2] && alarm_min==TIME[1])  //闹钟	{					beep=1;		delay_ms(100);		beep=0;		delay_ms(100);  		beep=1;		delay_ms(100);		beep=0;		LcdWriteCom(0x80);		LcdWritestr("   time out!    ");		LcdWriteCom(0xc0);		LcdWritestr("now time: ");		LcdWriteData(alarm_hour/16+0x30);		LcdWriteData(alarm_hour%16+0x30);		LcdWriteData(':'); 		LcdWriteData(alarm_min/16+0x30);		LcdWriteData(alarm_min%16+0x30);		LcdWritestr("    ");		delay_ms(500);		LcdClean();		}	else mode=DISPLAYDATA;	if(k4==0)	{		delay(1000);   //消除抖动 一般大约10ms		if(k4 ==0)	 //再次判断按键是否按下		{		 	alarmswitch=OFF;		}		while(k4==0);	}       }/******************************************************************************** 函 数 名         : main* 函数功能		   : 主函数* 输    入         : 无* 输    出         : 无*******************************************************************************/void main(void){	int ucount=0;	unsigned char lastSec;	beep= 0;	LcdInit();	 		//lcd初始化	//Ds1302Init();		  //时钟初始化	Ds18b20Init();		  //温度传感器初始化	SectorErase(0x2001);//	byte_write(0x2001,0x08);	   //执行一遍初始化//	byte_write(0x2201,0x00);//	byte_write(0x2401,0x00);	alarm_hour=byte_read(0x2601);	alarm_min=byte_read(0x2201);	alarmswitch=byte_read(0x2401);	while(1)			{		switch(mode)	//模式选择		{			case DISPLAYDATA:		//时间显示模式				Ds1302ReadTime(); //更新时间				if(TIME[0] !=  lastSec)				{					lastSec = TIME[0];					display_data();		  //显示时间 	 秒分时日月周年					displaytemp(Ds18b20ReadTemp());//显示温度					if(alarmswitch==ON && alarm_hour==TIME[2] && alarm_min==TIME[1])  //闹钟					{						mode = ALARMCLOCK; 					}				}	   		keypros(); 				//按键检测								break;			case MODIFYDATA:			  //时间修改模式				modify();				break;			case SETALARMCLOCK:			   //设置闹钟模式				setalarmclock();				break;			case ALARMCLOCK:			   //闹钟模式				alarmclock();				break;		}			}				}

项目问题

一、仿真问题

由于代码是基于实物设计的,部分功能不能完全仿真运行,不能运行的内容有EEPROM的存取,温度的读取

1、闹钟、时间不能调或者一起动?

由于调节闹钟会设计EEPROM的存取,所以不能正常显示读取到EEPROM的内容,需要该功能需要删除掉电存储功能

2、不日期显示异常,显示???,星期不显示的问题?

由于日期显示是0-9,星期显示是1-7,当显示的数据超过这个值时就会显示不正常,仿真的话需要适当修改代码,实物需要重新设置时间,就可以正常显示

完整代码可进群免费领取!!!

嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击下方链接,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦!

点击这里找小助理0元领取:扫码进群领资料

标签: #万年历数据库源码