51单片机数字钟LCD显示年月日闹钟纪念日功能完整测试成功版.docx
《51单片机数字钟LCD显示年月日闹钟纪念日功能完整测试成功版.docx》由会员分享,可在线阅读,更多相关《51单片机数字钟LCD显示年月日闹钟纪念日功能完整测试成功版.docx(30页珍藏版)》请在冰点文库上搜索。
51单片机数字钟LCD显示年月日闹钟纪念日功能完整测试成功版
实现功能
基于内部定时器的走时、调时、整点报时(蜂鸣器、LED)、3个闹钟设置,LCD显示时、分、秒、年、月、日、5个按键操作,添加纪念日功能。
题目:
单片机电子钟
院(系):
专业:
学号:
姓名:
2011年11月11日
摘要
...
关键词:
单片机AT89C511602液晶显示器
2.实验内容
2.1电子钟的仿真及原理图
原理图如下:
2.2电子钟的PCB封装图
2.3AT89C51的工作原理
AT89C51是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含4kbytes的可反复擦写的只读程序存
储器(PEROM)和128bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,
兼容标准MCS-51指令系统,片内置通用8位中央处理器(CPU)和Flash存储单元,功能强大AT89C51单片机可为您提
供许多高性价比的应用场合,可灵活应用于各种控制领域。
3、功能特性概述:
AT89C51提供以下标准功能:
4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个16位定时/计
数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
同时,AT89C51可降至0Hz的静态逻
辑操作,并支持两种软件可选的节电工作模式。
空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及
中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
3.1主要性能参数:
·与MCS-51产品指令系统完全兼容
·4k字节可重擦写Flash闪速存储器
·1000次擦写周期
·全静态操作:
0Hz-24MHz
·三级加密程序存储器
·128×8字节内部RAM
·32个可编程I/O口线
·2个16位定时/计数器
·6个中断源
·可编程串行UART通道
·低功耗空闲和掉电模式
4、电子钟工作原理:
利用51单片机内部定时计数器功能产生1S的计时,通过设定好的变量及函数分别按一定进制累加到时、分、秒、日、月、年上,通过按键扫描完成时间修改及闹钟设置,最后通过LCD1602显示时间,通过蜂鸣器及LED进行整点报时和闹钟报时。
5、通用1602液晶介绍:
6、电子钟源程序程序
/*********************************************************************
使用说明:
K1键为菜单选项:
单击→进入位选择修改;双击:
修改;
K2键为上调键;K3键为下调键;K4键为退出修改;
K5键为闹钟时间设置键;按一次:
闹钟一;两次:
闹钟二;三次:
闹钟三;四次:
重置五次:
纪念日
**********************************************************************/
#include
/********************************************************************
位定义
*********************************************************************/
sbitRS=P2^0;//功能数据选择位
sbitRW=P2^1;//读写选择位
sbitE=P2^2;//使能位0
sbitbusy=P0^7;//lcd忙标位
sbitmenu=P1^0;//菜单及确定
sbitinc=P1^1;//增一
sbitdec=P1^2;//减一
sbitquit=P1^3;//退出
sbitsound=P1^4;//闹钟控制
/*********************************************************************
全局变量
**********************************************************************/
unsignedchardatasec20,sec,min,hour,amin1,ahour1,amin2,ahour2,amin3,ahour3,temp,year1,year2,month,day,amonth,aday;//计秒,秒,分,时
unsignedchardatatimebuf[]={0,0,0x3a,0,0,0x3a,0,0,0,0,0,0,0x2d,0,0,0x2d,0,0};//存放时间
unsignedcharkey;//按键标志
unsignedchartime=0;//记录按menu键的次数
unsignedcharplace=0x84;//记录光标的位置
unsignedcharsignal=0;//光标与时间值增减标志位//0光标1时间值
/*********************************************************************
函数申明
**********************************************************************/
voiddelay(unsignedcharms);//延时函数
voidcbusy();//测试lcd忙碌状态函数
voidwrcom(unsignedcharcmd);//写指令函数
voidwrdat(unsignedchardat);//写数据函数
voidlcdinit();//lcd初始化函数
voidprotime();//时间处理函数
voiddisplay();//时间显示函数
unsignedcharscankey();//按键扫描
voidkeywork();//按键功能处理函数
voidnaoling1();
voidnaoling2();
voidnaoling3();
/*********************************************************************
延时函数
**********************************************************************/
voiddelay(unsignedcharms)
{
unsignedchari;
unsignedcharm=4;
while(ms--)
{
for(i=0;i<20;i++)
{
do
{}while(m--);
}
}
}
/*********************************************************************
测试lcd忙碌状态函数
**********************************************************************/
voidcbusy()
{
do
{P0=0xff;
RS=0;
RW=1;
E=0;
E=0;
busy=P0&0x80;
E=1;
}while(busy!
=0);
}
/*********************************************************************
写指令函数
**********************************************************************/
voidwrcom(unsignedcharcmd)
{
P0=cmd;
RS=0;
RW=0;
E=0;
cbusy();
E=1;
}
/*********************************************************************
写数据函数
**********************************************************************/
voidwrdat(unsignedchardat)
{
P0=dat;
RS=1;
RW=0;
E=0;
cbusy();
E=1;
}
/*********************************************************************
lcd初始化函数
**********************************************************************/
voidlcdinit()
{
wrcom(0x01);//清屏
wrcom(0x38);//8位总线,5*7点阵
wrcom(0x14);//文字不动光标自动右移
wrcom(0x0c);//开显示光标不显不闪
}
/*********************************************************************
定时器0中断产生秒
**********************************************************************/
voidtime0()interrupt1/*定时中断0*/
{
TL0=0xb0;//定时50ms
TH0=0x3c;
sec20++;//计数到一秒
protime();
}
/*********************************************************************
闹铃函数
**********************************************************************/
voidnaoling1()
{
amin1=min;
ahour1=hour;
}
voidnaoling2()
{
amin2=min;
ahour2=hour;
}
voidnaoling3()
{
amin3=min;
ahour3=hour;
}
/*********************************************************************
时间处理函数
**********************************************************************/
voidprotime()
{
if(sec20>19)//一秒到
{
sec20=0;
sec++;
}
if(sec>59)
{
sec=0;
min++;
}
if(min>59)
{
min=0;
hour++;
}
if(hour>23)
{
hour=0;
day++;
}
if(day>31)
{
day=0;
month++;
}
if(month>12)
{month=0;
year2++;}
timebuf[0]=sec%10+48;//时间数据更新
timebuf[1]=sec/10+48;
timebuf[3]=min%10+48;
timebuf[4]=min/10+48;
timebuf[6]=hour%10+48;
timebuf[7]=hour/10+48;
timebuf[8]=year1/10+48;//时间数据更新
timebuf[9]=year1%10+48;
timebuf[10]=year2/10+48;//时间数据更新
timebuf[11]=year2%10+48;
timebuf[13]=month/10+48;
timebuf[14]=month%10+48;
timebuf[16]=day/10+48;
timebuf[17]=day%10+48;
display();
/*if(min==0&&sec==0){sound=0;delay
(1);sound=1;delay
(1);
sound=0;delay
(1);sound=1;delay
(1);sound=0;delay
(1);sound=1;delay
(1);
}*/
if(min==0&&sec==0||amin1==min&&ahour1==hour&&sec==0||amin2==min&&ahour2==hour&&sec==0||amin3==min&&ahour3==hour&&sec==0||aday==day&&amonth==month&&min==0&&sec==0&&hour==0)
{sound=0;}
if(sec>5){sound=1;}
}
/*********************************************************************
时间显示函数
**********************************************************************/
voiddisplay()
{
unsignedchart;
//wrcom(0x80);
//wrdat(0xfb);
wrcom(0x84);
for(t=8;t>=1;t--)
{
wrdat(timebuf[t-1]);
}
wrcom(0xc3);
for(t=7;t<=16;t++)
{
wrdat(timebuf[t+1]);
}
if(amin1!
=61)
{wrcom(0xc1);
wrdat(0x41);
}
}
/*********************************************************************
按键扫描
**********************************************************************/
unsignedcharscankey()
{
if(P1!
=0xff)//判断是否有键按下
{
delay
(2);//延时消抖
if(P1!
=0xff)
{
switch(P1)
{
case0xfe:
{P1=0xff;while(P1!
=0xff);return
(1);}break;//判断所按键值并等
case0xfd:
{P1=0xff;while(P1!
=0xff);return
(2);}break;//等待按键松开,再
case0xfb:
{P1=0xff;while(P1!
=0xff);return(3);}break;//返回键值
case0xf7:
{P1=0xff;while(P1!
=0xff);return(4);}break;
case0x7f:
{P1=0xff;while(P1!
=0xff);return(5);}break;
}
}
}
else
return(0);
}
/*********************************************************************
按键功能处理函数
**********************************************************************/
voidkeywork()
{
key=scankey();
switch(key)
{
case1:
//按下menu键
{
time++;//menu键按下次数
EA=0;//关中断停止计时产生秒
if((time%2)==0)//判断按下是否为修改时间的状态
{
wrcom(place);
wrcom(0x0f);//光标显、闪
signal=1;//修改时间模式
}
else
{
wrcom(place);
wrcom(0x0e);//光标显,不闪
signal=0;//选择修改位模式
}
}break;
case2:
//按下inc键
{
if(signal==0)//修改位模式下
{
place++;//显示位置循环移动
wrcom(place);
if(place==0x8c)
place=0xc2;
if(place>=0xcd)
place=0x83;
}
else
switch(place)//修改时间值模式下
{
case0x84:
{
wrcom(0x84);//保证光标闪烁位置和当前位置一至
wrcom(0x0f);
timebuf[7]++;
if(timebuf[7]>50)
timebuf[7]=48;
display();
wrcom(0x84);
}break;
case0x85:
{
wrcom(0x85);
wrcom(0x0f);
timebuf[6]++;
if(timebuf[7]<50)
{
if(timebuf[6]>57)
timebuf[6]=48;
}
else
{
if(timebuf[6]>51)
timebuf[6]=48;
}
display();
wrcom(0x85);
}break;
case0x86:
break;
case0x87:
{
wrcom(0x87);
wrcom(0x0f);
timebuf[4]++;
if(timebuf[4]>53)
timebuf[4]=48;
display();
wrcom(0x87);
}break;
case0x88:
{
wrcom(0x88);
wrcom(0x0f);
timebuf[3]++;
if(timebuf[3]>57)
timebuf[3]=48;
display();
wrcom(0x88);
}break;
case0x89:
break;
case0x8a:
{
wrcom(0x8a);
wrcom(0x0f);
timebuf[1]++;
if(timebuf[1]>53)
timebuf[1]=48;
display();
wrcom(0x8a);
}break;
case0x8b:
{
wrcom(0x8b);
wrcom(0x0f);
timebuf[0]++;
if(timebuf[0]>57)
timebuf[0]=48;
display();
wrcom(0x8b);
}break;
case0xcc:
{
wrcom(0xcc);
wrcom(0x0f);
timebuf[17]++;
if(timebuf[17]>57)
timebuf[17]=48;
display();
wrcom(0xcc);
}break;
case0xcb:
{
wrcom(0xcb);
wrcom(0x0f);
timebuf[16]++;
if(timebuf[16]>51)
timebuf[16]=48;
display();
wrcom(0xcb);
}break;
case0xc9:
{
wrcom(0xc9);
wrcom(0x0f);
timebuf[14]++;
if(timebuf[14]>57)
timebuf[14]=48;
display();
wrcom(0xc9);
}break;
case0xc8:
{
wrcom(0xc8);
wrcom(0x0f);
timebuf[13]++;
if(timebuf[13]>49)
timebuf[13]=48;
display();
wrcom(0xc8);
}break;
}
}break;
case3:
//按下dec键
{
if(signal==0)
{
place--;
wrcom(place);
wrcom(0x0e);
if(place==0xc2)
place=0x8c;
if(place==0x83)
place=0xcd;
if(place>=0xcd)
place=0x83;
}
else
switch(place)
{
case0x84:
{
wrcom(0x84);
wrcom(0x0f);
timebuf[7]--;
if(timebuf[7]<48)
timebuf[7]=50;
display();
wrcom(0x84);
}break;
case0x85:
{
wrcom(0x85);
wrcom(0x0f);
timebuf[6]--;
if(timebuf[7]<50)
{
if(timebuf[6]<48)
timebuf[6]=57;
}
else
{
if(timebuf[6]<48)
timebuf[6]=51;
}
display();
wrcom(0x85);
}break;
case0x86:
break;
case0x87:
{
wrcom(0x87);
wrcom(0x0f);
timebuf[4]--;
if(timebuf[4]<48)
timebuf[4]=53;
display();
wrcom(0x87);
}break;
case0x88:
{
wrcom(0x88);
wrcom(0x0f);
timebuf[3]--;
if(timebuf[3]<48)
t