单片机万年历.docx
《单片机万年历.docx》由会员分享,可在线阅读,更多相关《单片机万年历.docx(44页珍藏版)》请在冰豆网上搜索。
单片机万年历
电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、时、分、秒进行计时等很多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、时、分、秒等信息,还具有时间校准等功能。
本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
在硬件与软件设计时,没有良好的基础知识和实践经验会受到很大限制,每项功能实现时需要那种硬件,程序该如何编写,算法如何实现等,没有一定的基础就不可能很好的实现。
在编写程序过程中发现以现有的相关知识要独自完成编写任务困难重重,在老师和同学的帮助下才完成了程序部分的编写。
万年历的设计过程在硬件与软件方面进行同步设计。
硬件部分主要由AT89C51单片机,LED显示电路,以及调时按键电路等组成。
在单片机的选择上本人使用了AT89C51单片机,该单片机适合于许多较为复杂控制应用场合。
软件方面主要包括日历程序、时间调整程序,显示程序等。
程序采用高级语言C进行编写,以便更简单地实现调整时间。
所有程序编写完成后,在确定没有问题后,在Proteus软件中嵌入单片机内进行仿真。
最后总在老师同学的帮助以及自己的努力下完成了此次电子万年历的设计。
二、系统功能说明
1、设计要求:
1、具有年、月、日、星期、时、分、秒等功能;
2、具备年、月、日、星期、时、分、秒调整校准功能;
2、单片机芯片的选择方案和论证:
采用89C51芯片作为硬件核心,数码管显示,为使用户更清楚更明白,万年历的日期和时间是分开显示,同时分别对应两个74LS138芯片用于控制数码管显示,还有74LS373译码器芯片,74LS21芯片是用于控制键盘的功能。
如图所示:
74LS138的八个输出引脚,任何时刻要么全为高电平1也就是芯片处于不工作状态,要么只有一个为低电平0,其余7个输出引脚全为高电平1。
如果出现两个输出引脚同时为0的情况,说明该芯片已经损坏。
洞洞板/万能板成品
图片左下角有地址-有录像
74LS373原理图
当74LS373用作地址锁存器时,应使OE为低电平,此时锁存使能端G为高电平时,输出Q1~Q8状态与输入端D1~D8状态相同;当G发生负的跳变时,输入端D1~D8数据锁入Q1~Q8。
51单片机的ALE信号可以直接与74LS373的G连接。
在MCS-51单片机系统中,常采用74LS373作为地址锁存器使用,其连接方法如上图所示。
其中输入端1D~8D接至单片机的P0口,输出端提供的是低8位地址,G端接至单片机的地址锁存允许信号ALE。
输出允许端OE接地,表示输出三态门一直打开。
显示模块选择方案:
采用LED数码管动态扫描,LED数码管价格适中,对于显示数字最合适,而且采用动态扫描法与单片机连接时,占用的单片机口线少。
使用多个数码管显示LED数码管是利用二极管发光显示数字和字母,具有亮度大、接口设计比较容易,价格相对较便宜等优点,所以采用了LED数码管作为显示。
数码管电路
3、键盘的选择
采用独立式按键电路。
每个键单独占有一根I/O接口线,每个I/O口的工作状态互不影响,此类键盘采用端口直接扫描方式。
而且在本次实验课设用的键盘很少,所以采用独立式按键比较实用。
4、实现定时:
直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、时、分、秒计数。
采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。
5、电路设计最终方案决定
综上各方案所述,对此次作品的方案选定:
采用AT89S51作为主控制系统;LED数码管动态扫描作为显示。
两个74LS138和一个74LS21芯片。
图-5LED动态扫描显示
实验心得:
经过了两个星期的学习和实验,我终于完成了单片机万年历课程设计。
从开始接到课设要求到万年历的实现,再到报告的完成,每走一步对我来说都是新的尝试与挑战,这也是我在大学期间独立完成的最大的项目。
在这段时间里,我学到了很多知识也有很多感受,我开始了独立的学习和试验,查看相关的资料和书籍,让自己头脑中模糊的概念逐渐清晰,使自己非常稚嫩作品一步步完善起来,每一次改进都是我学习的收获。
这次报告的书写也会使我终身受益,我感受到做报告是要用心去做的一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有自己的研究,就不会有所突破。
通过本次单片机课设,获得了丰富的理论知识,极大地提高了实践能力,单片机领域这对我今后进一步学习计算机方面的知识有极大的帮助。
参考文献
[1]李建忠.单片机原理及应用.西安电子科技大学出版2006.02
[2]张俊谟.单片机中级教程.北京航空航天大学出版2006.03
[3]余发山.单片机原理及及应用技术.中国矿业大学出版社2003.12
[4]杨凌霄.微型计算机原理及应用.中国矿业大学出版社2004.08
[5]何立民.单片机应用技术选编.北京航空航天大学出版社2000.08
[6]万光毅.单片机实验与实践教程.北京航空航天大学出版社2005.01
[7]周航慈.单片机程序设计基础.北京航空航天大学出版社1991.11
[8]黄遵熹.单片机原理接口与应用.西北工业大学出版社1997.05
[9]杨振江,杜铁军,李群.流行单片机实用子程序及应用实例[M].西安:
西安电子科技大学出版社,2002
[10]杨子文编单片机原理及应用西安电子科技大学出版社2006
[11]王法能编单片机原理及应用科学出版社2004
附源代码:
#include
sbitp1_0=P1^0;
sbitp1_1=P1^1;
sbitp1_2=P1^2;
sbitp1_3=P1^3;
sbitp1_4=P1^4;
sbitp3_2=P3^2;
unsignedcharcodezimal[13]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,
0x40,0x80,0x00,};
/*共阴极字形代码,显示0-9字形码,最后三个代码分别表示‘-’,‘.’‘熄灭’*/
unsignedintyear,month,day,hour,minute,second;//定义变量年,月,日,时,分,秒;
voiddelay();//延时函数;
voidxianshi(unsignedinth,min,s);//显示时间函数;
voidymdxianshi(unsignedintyear,month,day);//显示年月日;
voidfengming();//蜂鸣器函数;
intleap(unsignedintyear);//判断闰年函数;
unsignedinth,m,s=5;//记录定时时间;
unsignedintmode=1,td=0,yw=0;//状态;
voidmain()
{
year=2010;month=5;day=20;hour=23;minute=59;second=0;
/*初始化年,月,日,时,分,秒*/
TMOD=0x10;//定时器1;模式1;
TL1=0xb0;TH1=0x3c;定时时间为50ms
TR1=1;//打开定时器1
ET1=1;//定时器1溢出中断允许位
EX0=1;//外部中断0允许
IT0=1;//外部中断0触发方式为边沿触发
EA=1;
while
(1)//主循环;
{
if(hour==h&&minute==m&&second==s)fengming();//定时时间到,蜂鸣器响;
if(mode%2==0)ymdxianshi(year,month,day);//显示年月日
else
{
if(td%3==2)xianshi(h,m,s);//定时状态;
elsexianshi(hour,minute,second);//正常显示时间状态;
}
}
}
voiddelay()//延时函数;
{
unsignedinti;
for(i=0;i<400;i++);
}
voidymdxianshi(unsignedintyear,month,day)//年月日的显示与调整
{inti,j;
i++;
if(td%2==1&&yw%8==0&&i%2==0)//点亮年的第一个
{
P2=0x7f;
P0=zimal[12];
for(j=0;j<2000;j++);
}
else
{
P2=0x7f;
P0=zimal[year/1000];
delay();
}
if(td%2==1&&yw%8==1&&i%2==0)//点亮年的第二个
{
P2=0xbf;
P0=zimal[12];
for(j=0;j<1800;j++);
}
else
{
P2=0xbf;
P0=zimal[year%1000/100];
delay();
}
if(td%2==1&&yw%8==2&&i%2==0)//点亮年的第三个
{
P2=0xdf;
P0=zimal[12];
for(j=0;j<1800;j++);
}
else
{
P2=0xdf;
P0=zimal[year%100/10];
delay();
}
if(td%2==1&&yw%8==3&&i%2==0)//点亮年的第四个
{
P2=0xef;
P0=zimal[12];
for(j=0;j<1800;j++);
}
else//显示年
{
P2=0xef;
P0=zimal[year%10];
delay();
}
if(td%2==1&&yw%8==4&&i%2==0)//显示月点亮
{
P2=0xf7;
P0=zimal[12];
P2=0xfb;
P0=zimal[12];
for(j=0;j<1800;j++);
}
else
{
P2=0xf7;
P0=zimal[month/10];
delay();
P2=0xfb;
P0=zimal[month%10];
delay();
}
P2=0xef;//显示点
P0=zimal[11];
for(j=0;j<100;j++);
P2=0xfb;
P0=zimal[11];
for(j=0;j<100;j++);
if(td%2==1&&yw%8==5&&i%2==0)//显示日的第一个
{
P2=0xfd;
P0=zimal[12];for(j=0;j<1800;j++);
}
else
{
P2=0xfd;
P0=zimal[day/10];
delay();
}
if(td%2==1&&yw%8==6&&i%2==0)//显示日的第二个
{
P2=0xfe;
P0=zimal[12];
for(j=0;j<1800;j++);
}
else
{
P2=0xfe;
P0=zimal[day%10];
delay();
}
}
voidxianshi(unsignedinth,min,s)//显示时间函数;
{unsignedinti,j;
i++;
if(td%3!
=0&&yw%6==0&&i%2==0)
{P2=0x7f;//显示时的第一个;
P0=zimal[12];for(j=0;j<2000;j++);
}
else
{
P2=0x7f;
P0=zimal[h/10];
delay();
}
if(td%3!
=0&&yw%6==1&&i%2==0)//显示时的第二个
{
P2=0xbf;
P0=zimal[12];
for(j=0;j<2000;j++);
}
else
{
P2=0xbf;
P0=zimal[h%10];
delay();
}
//显示-
P2=0xdf;
P0=zimal[10];
delay();
if(td%3!
=0&&yw%6==2&&i%2==0)//显示分的第一个;
{
P2=0xef;
P0=zimal[12];for(j=0;j<2000;j++);
}
else
{
P2=0xef;//显示分的第二个;
P0=zimal[min/10];
delay();
}
if(td%3!
=0&&yw%6==3&&i%2==0)
{
P2=0xf7;
P0=zimal[12];
for(j=0;j<2000;j++);
}
else
{
P2=0xf7;
P0=zimal[min%10];
delay();
}
P2=0xfb;//显示-
P0=zimal[10];
delay();
if(td%3!
=0&&yw%6==4&&i%2==0)//显示秒的第一个;
{
P2=0xfd;
P0=zimal[12];for(j=0;j<2000;j++);
}
else
{
P2=0xfd;;
P0=zimal[s/10];
delay();
}
if(td%3!
=0&&yw%6==5&&i%2==0)//显示秒的第二个
{
P2=0xfe;
P0=zimal[12];
for(j=0;j<2000;j++);
}
else
{
P2=0xfe;
P0=zimal[s%10];
delay();
}
}
voidex0()interrupt0//外部中断零;
{
unsignedinti;
if(p1_3==0)delay();
if(p1_3==0){mode++;td=0;}
if(p1_1==0)delay();
if(p1_1==0)yw++;//移位;
if(p1_0==0)delay();
if(p1_0==0)td++;//修改调整时间状态;
if(mode%2==0)//调整日期;
{if(td%2==1)
{for(i=0;i<10;i++);
if(p1_2==0)delay();
if(p1_2==0)//移位;
{if(yw%8==0)year+=1000;//调整对应位的数值;
if(yw%8==1){year+=100;if(year%100/10==0)year-=1000;}
if(yw%8==2){year+=10;if(year/10%10==0)year-=100;}
if(yw%8==3){year++;if(year%10==0)year-=10;}
if(yw%8==4)month++;
if(yw%8==6){day++;if(day%10==0)day-=10;}
if(yw%8==5)day+=10;
}
//if(year>=2500)year=0;//年份小于2500;
if(month>12)month=1;//月份小于12;
switch(month)//日期限制
{
case4:
case6:
case9:
case11:
if(day>30)day=1;break;//4,6,9,11月30天;
case2:
{if(leap(year))//闰年2月29天;
while(day>29)day=1;
else
while(day>28)day=1;//非闰年28天;
}break;
default:
if(day>31)day=1;//1,3,5,7,8,10,12月31天;
}
}
}
//elseif(td%3==1)//调整时间;
elseif(td%3==1)
{
ET1=0;//时钟中断
for(i=0;i<10;i++);
if(p1_2==0)delay();
if(p1_2==0)
{
if(yw%6==1){hour++;if(hour%10==0)hour-=10;}
if(yw%6==0)hour+=10;
if(yw%6==3){minute++;if(minute%10==0)minute-=10;}
if(yw%6==2)minute+=10;
if(yw%6==5){second++;if(second%10==0)second-=10;}
if(yw%6==4)second+=10;
}
if(hour>23)hour=0;
if(minute>59)minute=0;
if(second>59)second=0;
}
else//定时状态;
{
ET1=1;
if(td%3==2)
{
for(i=0;i<10;i++);
if(p1_2==0)//定时;
{
if(yw%6==1){h++;if(h%10==0)h-=10;}
if(yw%6==0)h+=10;
if(yw%6==3){m++;if(m%10==0)m-=10;}
if(yw%6==2)m+=10;
if(yw%6==5){s++;if(s%10==0)s-=10;}
if(yw%6==4)s+=10;
}
if(h>23)h=0;
if(m>59)m=0;
if(s>59)s=0;
}
}
}
voidtime1()interrupt3//定时器1中断;
{
unsignedchari;
TF0=0;
TL0=0xb0;
TH0=0x3c;
i++;
if(i==20)//1秒钟到;
{
second++;
i=0;
}
if(second==60)//1分钟;
{
second=0;
minute++;
}
if(minute==60)//1小时;
{
minute=0;
hour++;
}
if(hour==24)//1天;
{
hour=0;
day++;
}
switch(month)//1月;
{
case4:
case6:
case9:
case11:
if(day>30){month++;day=1;}break;//4,6,9,11月30天;
case2:
{if(leap(year))
if(day>29){month++;day=1;}//闰年29天;
else
if(day>28){month++;day=1;}//非半闰年28天;
}break;
default:
if(day>31){month++;day=1;}//1,3,5,7,8,10,12月30天;
if(month>12)//1年;
{year++;
month=1;
}
}
}
voidfengming()//蜂鸣器;
{
intm,n;
for(m=0;m<=100;m++)
{p1_4=!
p1_4;
for(n=0;n<380;n++);
}
}
intleap(unsignedintyear)//判断闰年函数;
{
intleap;
if(year%4==0&&year%100!
=0||(year%400==0))
leap=1;
elseleap=0;
return(leap);
}
中文摘要
摘要:
在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。
若使用传统的机械式钥匙开锁,人们常需携带多把钥匙,使用极不方便,且钥匙丢失后安全性即大打折扣。
随着科学技术的不断发展,人们对日常生活中的安全保险器件的要求越来越高。
为满足人们对锁的使用要求,增加其安全性,用密码代替钥匙的密码锁应运而生。
密码锁具有安全性高、成本低、功耗低、易操作等优点。
在安全技术防范领域,具有防盗报警功能的电子密码锁逐渐代替传统的机械式密码锁,克服了机械式密码锁密码量少、安全性能差的缺点,使密码锁无论在技术上还是在性能上都大大提高一步。
随着大规模集成电路技术的发展,特别是单片机的问世,出现了带微处理器的智能密码锁,它除具有电子密码锁的功能外,还引入了智能化管理、专家分析系统等功能,从而使密码锁具有很高的安全性、可靠性,应用日益广泛。
随着人们对安全的重视和科技的发展,许多电子智能锁(指纹识别、IC卡辨认)已在国内外相继面世。
但是这些产品的特点是针对特定的指纹和有效卡,只能适用于保密要求的箱、柜、门等。
而且指纹识识别器若在公共场所使用存在容易机械损坏,IC卡还存在容易丢失、损坏等特点。
加上其成本较高,一定程度上限制了这类产品的普及和推广。
鉴于目前的技术水平与市场的接收程度,电子密码锁是这类电子防盗产品的主流。
基于以上思路,本次设计使用ATMEL公司的AT89C51实现一基于单片机的电子密码锁的设计,其主要具有如下功能:
(1)密码通过键盘输入,若密码正确,则将锁打开。
(2)报警、锁定键盘功能。
密码输入错误数码显示器会出现错误提示,若密码输入错误次数超过3次,蜂鸣器报警并且锁定键盘。
电子密码锁的设计主要由三部分组成:
4×4矩阵键盘接口电路、密码锁的控制电路、输出八段显示电路。
另外系统还有LED提示灯,报警蜂鸣器等。
密码锁设计的关键问题是实现密码的输入、清除、更改、开锁等功能:
(1)密码输入功能:
按下一个数字键,一个“-”就显示在最右边的数码管上,同时将先前输入的所有“-”向左移动一位。
(2)密码清除功能:
当按下清除键时,清除前面输入的所有值,并清除所有显示。
(3)开锁功能:
当按下开锁键,系统将输入与密码进行检查核对,如果正确锁打开,否则不打开。
主要的设计实施过程:
首先,选用ATMEL公司的单片机AT89C51,以及选购其他电子元器件。
第二步,使用DXP