提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、实验内容(简述)
电子日历是通过单片机控制液晶显示器LCD1602实现电子日历功能。实验使用主要设备为计算机和单片机。在Keil软件平台上使用C51语言编写“电子日历”的控制程序,并通过Proteus软件仿真后,将程序下载至实验箱单片机中。最终完成程序在实际硬件中的运行,实现电子日历的功能。
二、实验目的与要求:
实验目的:
- 学习使用Keil软件平台进行C51语言的项目建立、设计文件装载、程序录入、编译、软件仿真调试的方法
- 使用Proteus软件进行硬件电路的搭建、仿真及设计程序虚拟下载、故障排除硬件仿真的实验方法
- 综合应用C51语言中的宏命令、if语句、while语句、运算符、函数进行程序设计。学习模块化程序设计的特点及编程方法。
实验要求: - 以单片机为硬件基础,以C51语言为设计语言编程实现电子日历功能。具体如下:
(1)显示年、月、日
(2)显示时、分、秒 - 选作:通过单片机上提供的按键,实现电子日历的“调时”及“调日期”和“调秒”功能
三、实验仪器及设备、耗材:
① 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原理图的可以私信我。