C51实现一个电子日历(比较难)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、实验要求

1.以单片机为硬件基础,以C51语言为设计语言编程实现电子日历功能。具体如下:
(1)显示年、月、日
(2)显示时、分、秒
2.:通过单片机上提供的按键,实现电子日历的“调时”及“调日期”和“调秒”功能

二、使用步骤

1.引入库

代码如下(示例):

/**
 * @brief  使用LCD1602实现电子万年历
 * @author不留名
 * @date 2022-06-07 22:30:00
 * @version 2.0 
 * */
#include"REG51.H"
#define uint unsigned int
typedef unsigned char uchar;
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
sbit P2_3=P2^3;
sbit P2_4=P2^4;
sbit P2_5=P2^5;
uint Flag=0;//Flag用来判断按键按了几下
//闰年只影响2月份。因此只要用if进行判断就可以得到闰年的2月份
uint Pmonthnum[]={00,31,28,31,30,31,30,31,31,30,31,30,31};//平年数
uchar SegCode[]={0x3f,0x06,0x5b,0x4f};//用于显示按键按了几下
uint year=2020,month=2,day=28;
uint hour=23,minute=59,second=41;
uchar num=0,xq=4,count=0;
uchar code week[][3]={"MON","TUE","WED","THR","FRI","SAT","SUN"};
uchar Table1[]={" 2020-02-28 FRI"};
uchar Table2[]={"23:59:11"};
void DelayMs(uint ms);
void write_com(uchar command)//写指令
{
	RS=0;
	RW=0;
	E=0;
	P1=command;
	E=1;
	DelayMs(1);
	E=0;
}

void write_data(uchar date)//写数据
{
	RS=1;
	RW=0;
	E=0;
	P1=date;
	E=1;
	DelayMs(1);
	E=0;
}

void disp1(uchar add,uchar content)
{
	uchar shi,ge;
	shi=content/10;
	ge=content%10;
	write_com(add);
	DelayMs(2);
	write_data(shi+0x30);
	DelayMs(2);
	write_data(ge+0x30);
	DelayMs(2);
	
}

void disp2(uchar add,uchar content)
{
	uchar qian,bai,shi,ge;
	qian=content/1000;
	bai=(content/100)%10;
	shi=content%100/10;
	ge=content%10;
	write_com(add);
	DelayMs(2);
	write_data(qian+0x30);
	DelayMs(2);
	write_data(bai+0x30);
	DelayMs(2);	
	write_data(shi+0x30);
	DelayMs(2);
	write_data(ge+0x30);
	DelayMs(2);
	
}
void Init()
{
	write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
	write_com(0x0c);//设置开显示,不显示光标
	write_com(0x06);//写一个字符后地址++
	write_com(0x01);//显示清0,数据指针清0
	DelayMs(1);
	IE=0x82;//使用T0
	TMOD=0x01;//方式一
	TH0=15536/256;
	TL0=15536%256;
	TR0=1;
	write_com(0x80);//第一行
	for(num=0;num<15;num++)
	{
		write_data(Table1[num]);
		DelayMs(2);
	}
	write_com(0xc4);//第二行
	for(num=0;num<8;num++)
	{
		write_data(Table2[num]);
		DelayMs(2);
	}	
	write_com(0x8c);//显示星期
	for(num=0;num<3;num++)
	{
		write_com(week[xq][num]);
		DelayMs(1);
	}
}

void main(void)
{

	Init(); 
	P3=0x00;
	while(1)
	{   
	    if(P2_3==0)
		{
			DelayMs(20);//延时消抖
			if(P2_3==0)
			{				
			    while(P2_3==0);//松手检测	
				Flag++;
				if(Flag==4)
				   Flag=0;
			}
		}
		switch(Flag)
		{
			case 0:break;
			case 1:P3=SegCode[1];EA=0;
			   if(P2_4==0){DelayMs(20);if(P2_4==0){while(P2_4==0);second++;}}
			   if(P2_5==0){DelayMs(20);if(P2_5==0){while(P2_5==0);second--;}}
			   EA=1;break;
			case 2:P3=SegCode[2];EA=0;
			   if(P2_4==0){DelayMs(20);if(P2_4==0){while(P2_4==0);minute++;}}
			   if(P2_5==0){DelayMs(20);if(P2_5==0){while(P2_5==0);minute--;}}
			   EA=1;break;
			case 3:P3=SegCode[3];
			   if(P2_4==0){DelayMs(20);if(P2_4==0){while(P2_4==0);hour++;}}
			   if(P2_5==0){DelayMs(20);if(P2_5==0){while(P2_5==0);hour--;}}
			  EA=1;break;
			default:break;
		} 
		disp1(0xc4,hour);
		disp1(0xc7,minute);
		disp1(0xca,second);
	}//防止跑飞
}

void Timer0(void)interrupt 1
{
	TH0=15536/256;
	TL0=15536%256;
	count++;
	if(count==20)
	{
		count=0;
		second++;
		if(second>=60)
		{
			second=0;
			minute++;
			if(minute>=60)
			{
				minute=0;
				hour++;
				if(hour>=24)
				{
					hour=0;
					xq++;
					if(xq==7)
						xq=0;
                   if(((year%4==0&&year%100!=0)||year%400==0)&&month==2)
					{	//如果是闰年,二月份的天数应该为29
						day++;
						if(day>29)
						{
							day=1;
							month++;
							if(month>12)
							{
								year++;
								month=1;
								if(year>9999)
									year=0;
								 disp2(0x81,year);
							}
							disp1(0x86,month);
						}		
						disp1(0x89,day);
						write_com(0x8c);
						for(num=0;num<3;num++)
							write_data(week[xq][num]);
				  }
				else//不是闰年
				  {
					 day++;
					if(day>Pmonthnum[month])
						{
							day=1;
							month++;
							if(month>12)
							{
								year++;
								month=1;
								if(year>9999)
									year=0;
								 disp2(0x81,year);
							}
							disp1(0x86,month);
						}
						disp1(0x89,day);
						write_com(0x8c);
						for(num=0;num<3;num++)
							write_data(week[xq][num]);
				   }
				}
			}
		}
	}				
}

void DelayMs(uint ms)
{
	uint i=0;
	do{
		for(;i<113;i++);
	}while(--ms);
}

三、实验原理图

请添加图片描述

总结

实验中遇到的最大的困难就是对于LCD1602的不熟悉。因此,我花了2小时来进行学习LCD1602基础知识的学习。因为上次实验,让我发现了proteus上仿真可能存在定时不准确的情况。因此本次实验proteus只是起到辅助的作用,单片机起到了主要作用。本次实验也只是对于LCD1602最基本的运用。当我LCD1602运用熟练之后,我也会学习功能更加丰富的单片机液晶显示模块。
最后,建议大家在进行学习单片机的时候,可以自己买一块开发版。

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值