以AT89S51单片机为核心的数字电子钟控制器_第1页
以AT89S51单片机为核心的数字电子钟控制器_第2页
以AT89S51单片机为核心的数字电子钟控制器_第3页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、、设计题目:设计一个以 AT89S51单片机为核心的数字电子钟控制器,实现电子钟的时间、日期交 替显示、闹钟功能,并可通过按钮开关或键盘切换显示内容、调整参数、设置闹钟,在单片 机实验板上模拟调试实现控制器的功能。二、设计目的:通过单片机应用产品的设计与调试过程,稳固课程所学理论知识,初步了解单片机应用系统设计与调试的方法。三、设计要求:1开机自检,检查相关接口及数码管显示器、指示灯、蜂鸣器等外设是否正常。2. 8位数码管显示器平常以一定的时间间隔、适宜的格式显示时间和日期信息,时间显示时、分、秒;日期显示年20002099、月、日;设置闹钟功能时显示时、分、开/关状态。3可通过按键设定时间、

2、日期、闹钟等参数、手动切换显示。按键可用独立式按键或 行列式键盘实现。设定参数过程有适宜的方式指示当前可修改的内容。4对开关量输入进行软件消抖动处理,参数的设定有容错处理,女口:小时不能超过23 ,日期中每月最大天数、闰年等。5用Protel设计可实现上述功能的控制器的原理图最小应用系统。四、总体方案设计及说明:本设计电子时钟系统,主控芯片采用AT89S51芯片。配合软件延时实现时、分、秒的计时。本系统设计采用此种软件控制方法来实现计时,通过定时器定时中断,使时间缓存单元数据加一,提供系统时间。同时可以通过独立键盘对电子时钟开始计时,暂停计时和结束计时的控制。单片机内的数据通过并行I/O接口输

3、入输出。并驱动八位LED数码管时、分、秒分别用2位数码管显示,动态显示数据。晶振及复位电路为单片机提供工作脉冲及复位 信号。五、 系统资源分配说明:接口电路逻辑图:D 口 UL5I4UIL.ilS'lMStfl. A1W31KfiiX2P10 pnPU PBPL4PISwKKETINTIZT:TI nELMTXD 畑VC匚3-3-器霜盅器:亍PAI 竝拆PA?RESET35JUE255ADJD.D1D3票D6D-醍常巒11VCG那 cao-71AD1Y31A11Y11A21Y>1A31Y3LW顶2A1m2A22Y21A32Y3TGVOC-20O P v Hh W "fr

4、42 I 1C 5 SEa一命aa !1 i-H e!_d_'L3p11?3;dp&缶af.'3底加図IKIi"754525K14 EB 8,I 111使用定时计数器0, TMO设置为0x01;晶振频率11.0592MHz下,定时50ms 的计数初值经过计算为 4c00H (2M6-46080=4c00H), TH0设置为0x4c, TL0设 置为0x00。五、软件流程图及说明1.闹钟显示是前2位数码管显示CL前2位数码 管显示0P后6位数码管分别显示“-、小时的2位、“-分钟的2位按键扫描,判断有没有 按键,假设有按键那么退出 闹钟显示闹钟显示子程序,8个数

5、码管显示已经设置好的闹钟时间,进行按键扫描,判断有没有 按键,假设有就去执行相应的功能,日期显示子程序和时间显示子程序和闹钟显示子程序类似。2.键盘子程序 按键扫描:功能扫描:3中断子程序设置定时50ms的初值为4c00Ht中断20次,秒单元加1秒单元清零,分单元加1六、系统功能与操作说明:数字时钟能显示实时时间 HH-MM-SS 、日期20YY.MM.DD 于LED数码管,并可 以修改时间、日期。可以设置闹钟,时间到时,蜂鸣器会响起。按切换键可以在时间、日期、 闹钟时间中切换。时间、日期、闹钟时间可调,按外部中断键时间暂停,进入时间、日期、 闹钟时间设置,此时可以矩阵键盘输入时间日期, 输入

6、完后确认键时间按照设置的值接着走。键盘用行列式键盘,按键定义如下列图所示。主要的按键有:1数字键“ 0 “9,用于设置时输入时间和日期,正常工作时无效。2“时间设置、“日期设置、“闹钟设置,用于进入相应功能的设置状态。3“闹钟开关在闹钟设置状态时,用于设置闹钟开或关,正常工作时,用于手动关 闹铃的声音。4 “确认用于设置参数确实认,并检查参数是否合理,如果符合要求,那么参数有效; 否那么本次修改无效,保持原值。正常工作情况下按该键无操作。5“显示切换用于正常工作时手动切换时间、日期的显示。R4K5RtK7KSK»K10 Kll七、调试记录:1、确定课程设计课题为数字电子钟,并查找相关

7、资料。2、熟悉实验板数码管、两个 8255、键盘、LED等硬件资源的使用,弄清楚其对应的地址。3、调试出可以扫描矩阵键盘输入的数的程序,并在数码管上显示出来当前按下的键值。4、调试出可以显示时分秒和日期的时钟程序,并可以通过 4 个按键进行控制 分别为进入退出时间设置、时增 1、分增 1、秒增 1,并可以切换时间和日期。5、调试闹钟的显示和设置程序,时间到了所设置的时间时蜂鸣器响起。6、时间可以走,但只能通过在程序中给对应时间日期字节地址预先设置初始值,时钟根据 该初始时间接着走, 不能通过矩阵键盘输入时间日期。 最后查阅资料并询问同学终于解决了 这个问题。7、对整个程序做进一步优化处理,使其

8、更稳定,修改其中的一些瑕疵,加上注释,方便以 后读程序。八、实验设计总结 :通过努力终于设计出一个以 AT89S51 单片机为核心的数字电子钟控制器,实现电子钟 的时间、日期交替显示、闹钟功能,并可通过按钮开关或键盘切换显示内容、调整参数、设 置闹钟。这次实验我收获了许多,得到了许多书本上学不到的知识。 1、单片机的软件设计通常要考虑以下几个方面的问题:1根据软件功能要求,将系统软件划分为假设干个相对独立的局部,设计出合理的总 体结构,使软件开发清晰、简洁和流程合理;2培养良好的编程风格,如考虑结构化程序设计、实行模块化、子程序化。既便于 调试、链接,又便于移植和修改;3绘制程序流程图,再根据

9、流程图写程序;4合理分配系统资源;5为程序参加注释,提高可读性,便于以后修改移植复用; 2、关于程序的调试问题:1软件程序的调试应先分模块调试,统调是最后一环。通过各个模块程序的调试, 使程序逐渐趋于完整、正确,最后将各个模块组合起来,统调程序。2充分利用实验板上的其他空余硬件资源来协助调试程序,比方,可以用CPL P1.X来设置指示灯, 用来指示有没有调用键盘扫描子程序、 用来指示有没有扫描到键值、 用来指 示外部中断、定时器 0 和定时器 1 有没有工作等等。附录:#include <reg51.h>#include <absacc.h>#define PA XBY

10、TE0x0fefc#define PB XBYTE0x0fefd#define PC XBYTE0x0fefe#define CTL XBYTE0x0feff#define uchar unsigned charuchar ms20;sbit sou nd=P32;uchar open1=-1;/ 闹钟关闭code led19=0x0C0,0x0F9,0x0A4,0x0B0,0x99,0x92,0x82,0x0F8,0x80,0x90,0x88,0x83,0x0c6,0x0a1,0x86,0x8e,0x0bf,0x8c,0x0c7;code Table16=0x7e,0x0ee,0x0ed,0

11、x0eb,0x0de,0x0dd,0x0db,0x0be,0x0bd,0x0bb,0x0e7,0x0d7,0x0b7,0x77,0x7b,0x7d;structuchar hour;uchar minute;uchar second;uchar hour1;/ 闹钟小时uchar minute1;/ 闹钟分钟int year;uchar month;uchar day;time=23,59,55,00,00,2021,11,11;void delay()uchar i;for(i=0;i<200;i+);/*200个时钟周期 */void scan(uchar x)uchar i,tb,

12、tc=0x80;for(i=0;i<8;i+)tb=DBYTEx+i;PA=ledtb;/*送字段码*/PB=tc;/*送字位码*/tc>>=1;/*右移一位*/delay();int fastfound()uchar keyin;CTL=0x81; PC3PC0 为输入,PC7PC4为输出PC=OxOf; / 所有行(PC7PC4 置 0keyin=PC; / 读取键盘 if(keyin=0x0f) return 0;/无键按下,返回 0else return 1; /有键按下,返回 1int keyfound()uchar keyvalue,keyin_i,keyin_j

13、,keyin;uchar i;CTL=0x81;/PC3PC0 为输入,PC7PC4为输出PC=0x0f;keyin_j=PC;/ 读取列值CTL=0x88;/PC3PC0 为输出,PC7PC4(所有行)为输入PC=0x0f0;keyin_i=PC;/ 读取行值 keyin=keyin_j|keyin_i; / 形成行列组合 for(i=0;i<16;i+) if(Tablei=keyin)keyvalue=i; break;return keyvalue;void showclock() / 显示闹钟int a; uchar key=1;while(key=1) key=fastfou

14、nd();/消除按功能键时产生的影响for(a=0;a<800;a+) if(open1=1) DBYTE0x57=0;DBYTE0x58=17;显示"P",与前一个单元组合成"0P",表示闹钟已经翻开 elseDBYTE0x57=0x0c;DBYTE0x58=18;/ 显示 "L", 与前一个单元组合成 "CL", 表示闹钟已经关闭 DBYTE0x59=0x10; DBYTE0x5a=time.hour1/10; DBYTE0x5b=time.hour1%10;DBYTE0x5c=0x10;DBYTE0x5

15、d=time.minute1/10; DBYTE0x5e=time.minute1%10; scan(0x57);if(fastfound()=1) key=keyfound();if(key=0x0a)break;void rq() / 显示日期int a;uchar key=1;while(key=1) key=fastfound();/ 消除按功能键时产生的影响 for(a=0;a<800;a+)DBYTE0x47=time.year/1000; DBYTE0x48=time.year%1000/100; DBYTE0x49=time.year%100/10; DBYTE0x4a=

16、time.year%10; DBYTE0x4b=time.month/10;DBYTE0x4c=time.month%10;DBYTE0x4d=time.day/10;DBYTE0x4e=time.day%10;x'scan(0x47); if(fastfound()=1)/ 有键按下key=keyfound();/ 获得键值 if(key=0x0a) / 如果又按了显示切换键,那么显示闹钟时间 showclock();break;uchar isleap(int x) /判断闰年if(x%4=0 && x%100!=0) | (x%400=0) return 1;el

17、se return 0;void datechange()while(1)if(time.month=1 && time.day<31) time.day+;break;if(time.month=1 && time.day=31) time.month+;time.day=1;break; if(isleap(time.year) /是闰年if(time.month=2 && time.day<29) time.day+;break; if(time.month=2 && time.day=29) time.mont

18、h+;time.day=1;break; else / 不是闰年if(time.month=2 && time.day<28) time.day+;break;if(time.month=2 && time.day=28) time.month+;time.day=1;break; if(time.month=3 && time.day<31) time.day+;break; if(time.month=3 && time.day=31) time.month+;time.day=1;break; if(time.m

19、onth=4 && time.day<30) time.day+;break; if(time.month=4 && time.day=30) time.month+;time.day=1;break; if(time.month=5 && time.day<31) time.day+;break; if(time.month=5 && time.day=31) time.month+;time.day=1;break; if(time.month=6 && time.day<30) time.d

20、ay+;break; if(time.month=6 && time.day=30) time.month+;time.day=1;break; if(time.month=7 && time.day<31) time.day+;break; if(time.month=7 && time.day=31) time.month+;time.day=1;break; if(time.month=8 && time.day<31) time.day+;break; if(time.month=8 && ti

21、me.day=31) time.month+;time.day=1;break; if(time.month=9 && time.day<30) time.day+;break; if(time.month=9 && time.day=30) time.month+;time.day=1;break; if(time.month=10 && time.day<31) time.day+;break; if(time.month=10 && time.day=31) time.month+;time.day=1;brea

22、k; if(time.month=11 && time.day<30) time.day+;break;if(time.month=11 && time.day=30) time.month+;time.day=1;break;if(time.month=12 && time.day<31) time.day+;break;if(time.month=12 && time.day=31) time.month=1;if(time.year!=2099) time.year+;break;uchar checkall(u

23、char x)uchar i,h,m,s,month,d;int y;if(x=0x0c)/ 对闹钟设置进行判断for(i=3;i<8;i+)if(i=5)continue;/ 如果是原来的 "-", 就去判断下一个单元的按键是否合法 if(DBYTE0x57+i=0x10) return 0;/如果按键不是数字,结束h=DBYTE0x5a*10+DBYTE0x5b;m=DBYTE0x5d*10+DBYTE0x5e;if(h>24 | (h=24 && (h!=0 | s!=0) return 0;if(m>=60) return 0;re

24、turn 1;/ 按键合法返回 1if(x=0x0f)/ 对时间设置进行判断for(i=0;i<8;i+)if(i+1)%3=0) continue;/* 如果是原来的 "-", 就去判断下一个单元的 按键是否合法 */ if(DBYTE0x57+i=0x10) return 0;/如果按键不是数字,结束h=DBYTE0x57*10+DBYTE0x58;m=DBYTE0x5a*10+DBYTE0x5b;s=DBYTE0x5d*10+DBYTE0x5e;if(h>24 | (h=24 && (h!=0 | s!=0) return 0;if(m&g

25、t;=60) return 0;if(s>=60) return 0;return 1;/ 按键合法返回 1if(x=0x0e)/ 对日期设置进行判断for(i=0;i<8;i+)if(DBYTE0x57+i=0x10) return 0;/ 如果按键不是数字,结束y=DBYTE0x57*1000+DBYTE0x58*100+DBYTE0x59*10+DBYTE0x5a;month=DBYTE0x5b*10+DBYTE0x5c;d=DBYTE0x5d*10+DBYTE0x5e;if(y<2000 | y>2099) return 0;if(month=0 | month

26、>12) return 0;if(d=0 | d>31) return 0;if(month=1 && d>31) return 0;if(month=3 && d>31) return 0;if(month=4 && d>30) return 0;if(month=5 && d>31) return 0;if(month=6 && d>30) return 0;if(month=7 && d>31) return 0;if(month=8 &

27、& d>31) return 0;if(month=9 && d>30) return 0;if(month=10 && d>31) return 0;if(month=11 && d>30) return 0;if(month=12 && d>31) return 0;if(isleap(y) / 是闰年if(month=2 && d>29) return 0;else / 不是闰年if(month=2 && d>28) return 0;retu

28、rn 1;void setclock()uchar i,j,k,key,keyin;k=1;key=1;while(key=1) key=fastfound();/ 消除按功能键时产生的影响DBYTE0x57=0x10;DBYTE0x58=0x10;DBYTE0x59=0x10;DBYTE0x5a=0;DBYTE0x5b=0;DBYTE0x5c=0x10;DBYTE0x5d=0;DBYTE0x5e=0;for (i=0;i<2;i+)for(j=0;j<2;j+)while(k)key=fastfound();if(key=1)keyin=keyfound();k=0;/*scan

29、(0x57);/ 显示按键 if(keyin<0 |keyin>9 ) keyin=0x10;/DBYTE0x5a+i*3+j=keyin; while(key=1) key=fastfound();/*k=1; / 用于进入下一次按键状态如果有键按下,那么退出 while ; 等待按键 */如果按键的值非法,置为判断按键以后,手是否已放开放开,等待 */否那么,如果没DBYTE0x5a+i*3+j=0x10; / 设置该单元显示 "-"while(1) / 设置时间完成后,判断是否按了确认键key=fastfound();scan(0x57);if(key=1

30、) keyin=keyfound();if(keyin=0x0d)/* 判断按键是否为确认键,如果是,那么进行按键的判断;如果不是,那么等待 */ if(checkall(0x0c)=0) break;/如果按键非法,退出,保持原来的值time.hour1=DBYTE0x5a*10+DBYTE0x5b; time.minute1=DBYTE0x5d*10+DBYTE0x5e;break;void setdate()uchar i,k,key,keyin;k=1;key=1;while(key=1) key=fastfound();/ 消除按功能键时产生的影响 DBYTE0x57=time.ye

31、ar/1000;DBYTE0x58=time.year%1000/100;DBYTE0x59=time.year%100/10;DBYTE0x5a=time.year%10;DBYTE0x5b=time.month/10;DBYTE0x5c=time.month%10;DBYTE0x5d=time.day/10;DBYTE0x5e=time.day%10;for (i=0;i<8;i+)while(k)key=fastfound();if(key=1)keyin=keyfound();k=0;/scan(0x57);/ 显示按键如果有键按下, 那么退出 while; 否那么 , 等待按键

32、if(keyin<0 |keyin>9 ) keyin=0x10;/ DBYTE0x57+i=keyin; while(key=1) key=fastfound();/*如果按键的值非法,置为 "-"判断按键以后,手是否已放开如果没放开,等待 */k=1; / 用于进入下一次按键状态/ 设置时间完成后,判断是否按了确认键 while(1)key=fastfound();scan(0x57);if(key=1) keyin=keyfound();if(keyin=0x0d)/* 判断按键是否为确认键,如果是,那么进行按键的判断;如果不是,那么等待 */if(che

33、ckall(0x0e)=0) break;/ 如果按键非法,退出,保持原来的值 time.year=DBYTE0x57*1000+DBYTE0x58*100+DBYTE0x59*10 +DBYTE0x5a;time.month=DBYTE0x5b*10+DBYTE0x5c;time.day=DBYTE0x5d*10+DBYTE0x5e;break; void settime()uchar i,j,k,key,keyin;消除按功能键时产生的影响k=1;key=1;while(key=1) key=fastfound();/DBYTE0x57=0;DBYTE0x58=0;DBYTE0x59=0x

34、10;DBYTE0x5a=0;DBYTE0x5b=0;DBYTE0x5c=0x10;DBYTE0x5d=0;DBYTE0x5e=0;for (i=0;i<3;i+)for(j=0;j<2;j+)while(k)key=fastfound();if(key=1)keyin=keyfound();k=0;/*scan(0x57);/ 显示按键 if(keyin<0 |keyin>9 ) keyin=0x10;/ DBYTE0x57+i*3+j=keyin; while(key=1) key=fastfound();/*如果有键按下,那么退出 while ; 否那么,等待按键

35、 */如果按键的值非法,置为判断按键以后,手是否已放开如果没放开,等待 */k=1; / 用于进入下一次按键状态DBYTE0x57+i*3+j=0x10; / 设置该单元显示 "-" while(1) / 设置时间完成后,判断是否按了确认键key=fastfound();scan(0x57);if(key=1) keyin=keyfound();if(keyin=0x0d)/* 判断按键是否为确认键,如果是,那么进行按键的判断;如果不是,那么等待 */if(checkall(0x0f)=0) break;/ 如果按键非法,退出,保持原来的值 time.hour=DBYTE0

36、x57*10+DBYTE0x58;time.minute=DBYTE0x5a*10+DBYTE0x5b;time.second=DBYTE0x5d*10+DBYTE0x5e;break;void timechange() interrupt 1 / 秒加 1int i;TH0=0x4c; /晶振频率11.0592MHz下,定时50ms的计数初值TL0=0x00; 2X6-46080=4c00Hms20+;if( ms20>=20)time.second+;ms20=0;if(time.second>=60)time.minute+;time.second=0;if(time.minute>=60)time.hour+;time. minute =0;if(time.hour>=24)time.hour=0;datechange();DBYTE0x77=time.h

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论