电子万年历

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

一、实验内容(简述)

电子日历是通过单片机控制液晶显示器LCD1602实现电子日历功能。实验使用主要设备为计算机和单片机。在Keil软件平台上使用C51语言编写“电子日历”的控制程序,并通过Proteus软件仿真后,将程序下载至实验箱单片机中。最终完成程序在实际硬件中的运行,实现电子日历的功能。

二、实验目的与要求:

实验目的:

  1. 学习使用Keil软件平台进行C51语言的项目建立、设计文件装载、程序录入、编译、软件仿真调试的方法
  2. 使用Proteus软件进行硬件电路的搭建、仿真及设计程序虚拟下载、故障排除硬件仿真的实验方法
  3. 综合应用C51语言中的宏命令、if语句、while语句、运算符、函数进行程序设计。学习模块化程序设计的特点及编程方法。
    实验要求
  4. 以单片机为硬件基础,以C51语言为设计语言编程实现电子日历功能。具体如下:
    (1)显示年、月、日
    (2)显示时、分、秒
  5. 选作:通过单片机上提供的按键,实现电子日历的“调时”及“调日期”和“调秒”功能

三、实验仪器及设备、耗材:

① Keil μVision5软件
② Proteus仿真软件
③ 51开发版

四、设计原理、设计方案及流程等:

本次实验分为四个模块。分别为按键模块、显示模块、时钟模块和主控制模块。
按键模块:利用单片机上自带的独立按键。
显示模块:使用LCD1602液晶显示器。
时钟模块:时钟采用12KHZ
主控制模块:采用STC89C52
该系统采用定时器来进行计数。通过LCD1602来显示时间。按键来控制时分秒的加减。

五、实验操作

主要步骤:
① 绘制Proteus原理图
② 时钟设置子程序
③ 开启中断
成果分析:
在Proteus和单片机上,理论与实际时间都相符。

六、实验结论(包括实验数据、图表、程序):

1.实验原理图

在这里插入图片描述

2.代码

#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);
}

代码

实验原理图:

总结

需要注意的我已标注在代码上。需要proteus原理图的可以私信我。

  • 9
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值