《单片机课程设计报告基于51单片机时钟的LED显示(15页).doc》由会员分享,可在线阅读,更多相关《单片机课程设计报告基于51单片机时钟的LED显示(15页).doc(15页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-单片机课程设计报告基于51单片机时钟的LED显示-第 15 页一 需求分析本设计是基于51单片机时钟的LED显示,通过单片机产生计数功能,通过LED数码管显示,显示时间时、分、秒,并用按键进行时间调整,同时带有整点报时功能。二 总体设计1设计思路通过51内部定时器产生时钟来进行准确计时,用独立键盘来实现时钟的可调,最后由LED数码管来显示。2.器件选择AT89C52 74LS138 8位共阴数码管 7407 MAX232 串行口九针插头12M晶振 按键 电容 排阻3.开发环境KEIL Uvision4 4.下载工具STC-ISP-V3.5三 硬件电路分析该硬件电路由显示电路、电源电路、信号处
2、理电路、单片机最小系统、串口通信以及按键控制电路六部分构成。该单片机开发板具备了电源、复位、时钟、键盘、显示等电路,可用于编程开发单片机的多种控制功能。由于外部硬件电路已经确定,单片机各引脚已经连接好,其对应位也已经确定好,因此在进行程序设计前,要对AT89C52各引脚连接的电路以及所控制的电路进行分析,分析后确定了以下信息:(1)P0口连接数码管八段,通过写P0口来控制数码管显示的内容;(2)P1.0口控制着电路板上的绿色指示灯的亮灭,其中1为灭,0为亮;(3)P2口:P2.7 P2.4分别连接K1K4按键,编程时,需要通过读取P2.7 P2.4的值获取按键状态;P2.0 P2.2分别连接3
3、-8译码器的A、B、C输入端,编程时需要写P2.0 P2.2口来实现控制六个数码管的显示;P2.3连接3-8译码器的使能端,编程时需要对P2.3写入0,;(4)单片机复位电路已经连接好,复位键可以直接使用,编程时无需编写复位程序;(5)振荡电路已连接好,其中晶振为12MHz,通过利用中断进行精确计时;四 软件设计1进行软件设计前需要先学习下KEIL Uvision4和 STC-ISP-V3.5两款软件的使用方法。关于KEIL Uvision4软件使用时需要注意问题:1)新建工程后,会弹出一个“Select Device For Target”对话框,此时需要点开Atmel然后选择AT89C52
4、,确定;2)在刚建的工程下,新建file,编好文件保存时在给文件命名是一定要带上扩展名“.c”;3)编写好的C文件需要添加到当前Target下,编译前需要找到“Option For Target”对话框进行设置,把晶振频率设置为12MHz,点击“output”,在“create HEX fi”前打上勾,生成十六进制的文件,以用于下载到单片机内。关于STC-ISP-V3.软件使用时需要注意的问题:1)选择单片机型号(STC89C52RC);2)选择Clear Buffer (清缓冲区),Open File打开待烧录的.HEX文件 ;3)根据实际连接选择COM口,实际所用COM口可通过设备管理器查
5、询得到;4)冷启动。电路板断电后点击Download按钮,然后接通电路板电源,等待编程结束,成功下载到单片机内。2.程序设计思路本次要实现的功能是可调数字钟,分析后把程序分成五个子模块进行编写,其中五个子模块分别为时间处理子程序、显示子程序、整点报时子程序、按键扫描子程序以及中断子程序。3.各模块实现的功能以及分析(1)时间处理子程序该模块中把秒设置为六十进制,分钟设置为六十进制,小时设置为二十四进制,同时实现秒分和分时之间的进位。实验程序如下:void time_dis( void) if(sec=60) /秒钟设为60进制 sec=0; min+; if( min=60) /分钟设为60进
6、制 min=0; hour+; if(hour=24) /时钟设为24进制 hour=0; (2)显示子程序该程序实现数码管的显示。除了正常计时显示还需要考虑上调节状态下数码管的显示情况,因此需要用到一系列的条件判断语句。调节按键没有按下时,数码管显示时钟,此状态下,时与分和分与秒之间的小数点以2Hz的频率闪烁;一旦调节按键按下,则相应的调节位以2Hz的频率闪烁,由于调节时,只调时分秒的个位,十位一直显示即可。显示时的程序流图如下:开始Y0选通,数码管时的十位显示,写P0口Y1选通,数码管时的个位选通flash=0写P0口,数码管亮P0=0x00;数码管灭flash=0写P0口,小数点亮,P0
7、或上0X80写P0口,小数点灭按下调节键K4,adjust_key=3YNYNYN而对于显示分的子程序,同显示时的程序一样,判断条件为adjust_key=2,在写P0口时,写的分的十位和个位;而对于显示秒的子程序,判断条件为adjust_key=1由于小数点不需要闪烁,因此,如果没有按键按下,则直接把秒的个位值写进P0口即可,无需判断flash。(3)整点报时子程序整点报时子程序通过P2.7口控制,当K1(P2.7)按下时,通过变量baoshi_flag记录按键的状态,按键有0、1两个状态,0状态对应整点报时功能关,1状态对应着整点报时功能开,在分和秒都为0时,则报时,此时绿灯灭一下。该段程
8、序程序流图如下:开始K1(P2.7)按下baoshi_flag=baoshi_flag;baoshi_flag=1&sec=0&min=0绿灯灭(1)绿灯亮(0)YN(4)按键扫描子程序按键扫描子程序即扫描读取K1、K2、K3、K4,如果有按键按下,则做相应的处理。首先规定按键的功能:K4(P2.4):调节按键,当按一下K4时,由时间状态进入调节状态,调节标志变量adjust_flag=1,此时adjust_key=1,调秒;再按一下, adjust_key=2,则调分;再按一下,adjust_key=3,则调时;再按一下,adjust_key=4,adjust_flag=0,按一下K3或K4
9、,由调节状态便成为时钟显示状态。K3(P2.5):加按键,在调节状态下即adjust_flag=1,按一下K3按键则相应的调节位加1;K2(P2.6):减按键,在调节状态下即adjust_flag=1,按一下K2按键则相应的调节位减1。由于K4(P2.4)键按的次数不同所对应的调节状态不同,共有四种调节状态:调时、调分、调秒、确认,因此需要用一变量adjust_key(取值为1、2 、3、 4)来记录各调节状态,当按下按键K3(P2.5)或K2(P2.6)时,利用case(adjust_key)语句判断出是对哪一位进行加或减或是恢复时钟计时状态。编写该子程序时需要注意的问题:对按键需用延时进行
10、消抖处理,如果不消抖则无法正确调节。本实验程序中用的是多次调用显示子程序display()以实现一定的延时,做到消抖。如果此处用延时子程序,也能达到消抖的目的,但由于延时过程中未扫描显示数码管,当按键按下时,数码管会灭,显示效果不好。(5)中断子程序利用定时器0方式1,50ms中断一次。利用t和mstcnt自加记录中断次数,当十次中断后,flash取反,t归0重新计数,则flash变化频率为2Hz;当二十次中断后,sec自加1,则1秒sec加1,mstcnt归零重新计数。实现精确计时。计算定时初值。晶振频率为12MHz,机器周期为1微秒,要实现50ms中断一次,则计数初值为65536-5000
11、0=15536=3cb0(十六进制),因此计数初值为:TH0=0x3c;TL0=0xb0;工作方式设置:TMOD=0x01。中断服务子程序如下:timer(void) interrupt 1 using 0 /利用定时器0方式1,50ms中断一次,设置定时初值 TR0=0; TH0=0x3c; TL0=0xb0; TMOD=0x01; if(t9) t+; else t=0;flash=flash; /flash以2Hz的频率变化 if(con=0) if(mstcnt19) mstcnt+; else mstcnt=0;sec+; /1秒计时,秒加TR0=1; /开定时器注意的问题:在中断子
12、程序末尾一定要记得开定时器。(6)主程序 主程序中打开定时器,设置定时初值以及定时器的工作方式,然后利用while (1)语句,反复执行各个子程序即可。主程序如下:void main(void) P2=0xff; /初始化p2口,全设为1 TMOD = 0x01; /time0为定时器,方式1 TH0=0x3c; /预置计数初值 TL0=0xb0; EA=1; ET0=1; TR0=1; en=0; while (1) keyscan(); /按键扫描 time_dis(); /时间处理 display(); /显示时间 baoshi(); /整点报时 五 收获与总结通过为期一周的单片机课程设
13、计,收获很大。首先,以前在学习单片机的时候,老师所讲的全是汇编语言,而此次课程设计我用的是C语言,因此自己课下通过看相关单片机教学视频以及教学资料学习了基于51单片机的C语言程序的编写以及相关软件KEIL Uvision4、STC-ISP-V3.5的使用,通过自己反复实践编程下载,现在可以熟练使用这两款软件进行单片机开发。其次,通过此次单片机课程设计,更加深入掌握了51单片机的结构和原理,51单片机内部定时系统的开启和设置、中断调用和如何使用单片机内部时钟实现精确计时以及如何对单片机的双向口进行读写操作等。除此之外,也更加深入理解了数码管动态扫描显示原理。最后,通过连续几天来不断地编程下载和调
14、试,自己形成了一定的编程思维。起初,自己先是从网上搜集资料,通过对一系列的单片机C语言程序的研究,掌握到了基本的编程思路以及了解到要实现相关的功能应该采取何种操作。然后,根据自己的单片机课程设计数字钟的设计需求,先是实现基本的计时显示功能,这就需要编写好时间处理子程序、中断程序以及显示子程序,编写好后进行编译调试,无错误无警告后下载到开发板上,观察板子的显示情况,然后再根据具体情况具体的对程序进行改动。记得一开始自己把程序下载到板子上时,只显示不计数,然后自己就在想可能哪错了,能显示说明显示子程序没问题,问题出在时间处理子程序和中断子程序,最后检查出自己忘了打开定时器导致数字钟不计数,因此修改
15、后编译下载,正确显示并计数。当基本功能实现后,就开始考虑调节时间功能。调时需要扫描按键,因此编写按键扫描子程序。首先得对各按键功能进行定义,然后再编写程序。开始我用了三个按键分别控制时分秒的加,最后一个按键则为确认键,这时我发现有点资源浪费,四个按键全用了确只能加不能减,考虑到实际数字钟用一个键控制调节位,一个按键加,一个按键减,因此重新编写按键子程序。最后一个闲置的按键则用来实现了整点报时功能的控制。当把自己想实现的功能都实现后,接下来要做的就是完善程序,改善显示效果。在调节时让相应的位闪烁,并且按键按下后数码管上的显示不闪烁等等,其实完善程序也是一个相当艰难而且漫长的过程,调节位闪烁与不闪
16、烁需要改动的地方很多。比如,我在调节状态时,定时器已经关了,此时2Hz变化的变量flash不会变了,那么要想闪烁我就必须把定时器打开,但定时器打开后调节时时钟状态还在变化,秒个位一直在加一,因此我就又添了一个变量con,调节状态下,把con置1,恢复时间状态后把con清0,而sec自加前判断一下con标志位是否为0决定是否自加,这样就即可以实现调节位闪烁,同时sec不再自加。此次课程设计虽然单调但也充满了无穷的乐趣。在编程的过程中,出现过不少问题,有时出现好几十个错误,但是有时这好几十个错误竟会是少一个大括号或是大括号放错了位置引起的,把大括号放对后,0个错误。因此,只要自己按着思路一步步编是
17、不会出现太多错误的,这个时候自己一定要有耐心,耐心的根据错误位置及错误提示仔细的检查,不断地修改不断地编译,再修改再编译。这个过程中,使得自己以后编程中对于C中一些常见的错误也能准确快速地修改了。附:完整的单片机C程序#include#define uchar unsigned char #define uint unsigned int /宏定义/*七段共阴管显示定义*/ uchar code dispcode=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F;/*定义并初始化变量*/uchar sec=0;uchar min=0;uchar
18、 hour=0;uchar mstcnt=0; /计次数变量sbit a=P20;sbit b=P21;sbit c=P22; /3-8译码器三输入端sbit en=P23;sbit P2_4=P24; / 调时按键,根据按键次数确定调节位sbit P2_5=P25; /加按键sbit P2_6=P26; /减按键sbit P2_7=P27; / 整点报时按键,按一下整点报时开,再按一下整点报时关sbit green=P10; /整点报时显示灯,整点时灯灭一下uchar adjust_key=0; /记录调节按键次数变量bit adjust_flag=0; /按键调节标志bit baoshi_
19、flag=0; /报时标志变量uchar t=0; /记录中断次数变量,计数到10则归零bit flash=0; /以2HZ的频率变化bit con=0; /时钟计时控制变量/*函数声明*/void delay(uchar xms); /延时子程序void time_dis(); /时间处理子程序void display(); /显示子程序void keyscan(); /键盘扫描子程序void baoshi (); /整点报时子程序/*延时子程序*/void delay (uchar xms) uint i,j;for(i=0;ixms;i+)for(j=0;j125;j+);/*时间处理子
20、程序*/void time_dis( void) if(sec=60) /秒钟设为60进制 sec=0; min+; if( min=60) /分钟设为60进制 min=0; hour+; if(hour=24) /时钟设为24进制 hour=0; /*显示子程序*/void display(void) /*显示小时的十位*/ a=0;b=0;c=0; P0=dispcodehour/10; delay(3); /*显示小时的个位*/if(adjust_key=3) /若有按键按下,调节状态,相应的调节位闪烁 a=1;b=0;c=0; if(flash=0) /闪烁频率为2Hz,通过条件语句判
21、断变量flash的值实现 P0=(dispcode(hour%10); else P0=0x00;else /没有按键按下则为计时状态,数码管正常计数显示 a=1;b=0;c=0; if(flash=0) P0=(dispcode(hour%10)|0X80; else P0=(dispcode(hour%10); /对于时和分的个位在正常时间显示状态下,其数码管上的小数点以2Hz的频率闪烁delay(3); /*显示分的十位*/ a=0;b=1;c=0; P0=dispcodemin/10; delay(3); /*显示分的个位*/if(adjust_key=2) a=1;b=1;c=0;
22、if(flash=0) P0=(dispcode(min%10); else P0=0x00;else a=1;b=1;c=0; if(flash=0) P0=(dispcodemin%10)|0X80; else P0=(dispcodemin%10);delay(3); /*显示秒的十位*/ a=0;b=0;c=1; P0=dispcodesec/10; delay(3); /*显示秒的个位*/if(adjust_key=1) a=1;b=0;c=1; if(flash=0) P0=(dispcode(sec%10); else P0=0x00;else a=1;b=0;c=1; P0=d
23、ispcodesec%10; delay(3); /*整点报时子程序*/ void baoshi (void) if(P2_7=0) display(); display();display(); display();display(); /利用多次执行显示子程序以达到延时按键去抖动的目的 if(P2_7=0) /P2_7对应K1按键,按一次则开启整点报时功能,再按一下则关闭 baoshi_flag=baoshi_flag; if(baoshi_flag=1&sec=0&min=0) green=1; /整点到来时,绿灯灭一下 else green=0;/*按键扫描子程序*/void keys
24、can (void) /按键扫描 if(P2_4=0) /K4键 display(); display();display();display();display(); /消抖处理 if(P2_4=0) TR0=0; /有按键按下,则关定时器,停止计时 adjust_flag=1; /调节状态 if(adjust_key4) adjust_key+; else adjust_key=1; if(P2_5=0&adjust_flag=1) /K3加1键 display(); display();display();display();display(); if(P2_5=0) switch(ad
25、just_key) /定义各调节状态 case 1: /调秒 con=1; /秒计时标志量 TR0=1; /调节位2Hz亮灭闪烁,需开定时器,但时钟为调节状态不计时,通过con控制实现 if(sec59) sec+; else sec=0; break; case 2: /调分 con=1; TR0=1; if(min59) min+; else min=0; break; case 3: /调时 con=1; TR0=1; if(hour0) sec-; else sec=59; break; case 2: /调分 con=1; TR0=1; if(min0) min-; else min
26、=59; break; case 3: /调时 con=1; TR0=1; if(hour0) hour-; else hour=23; break; case 4:adjust_flag=0;/确认 TH0=0x3c; TL0=0xb0; TR0=1; con=0; display(); break; default:break; /*中断子程序*/ void timer(void) interrupt 1 using 0 /利用定时器0方式1,50ms中断一次,设置定时初值 TR0=0; TH0=0x3c; TL0=0xb0; TMOD=0x01; if(t9) t+; else t=0;
27、flash=flash; /flash以2Hz的频率变化 if(con=0) if(mstcnt19) mstcnt+; else mstcnt=0;sec+; /1秒计时,秒加TR0=1; /开定时器/*主函数*/void main(void) P2=0xff; /初始化p2口,全设为1 TMOD = 0x01; /time0为定时器,方式1 TH0=0x3c; /预置计数初值 TL0=0xb0; EA=1; ET0=1; TR0=1; en=0; while (1) keyscan(); /按键扫描 time_dis(); /时间处理 display(); /显示时间 baoshi(); /整点报时