《51单片机课程设计数字时钟设计.doc》由会员分享,可在线阅读,更多相关《51单片机课程设计数字时钟设计.doc(36页珍藏版)》请在三一办公上搜索。
1、福州大学MCS-51单片机课程设计题 目: 数字时钟 姓 名: 学 号: 学 院: 电气工程与自动化学院 专 业: 电机电器 年 级: 2009 起讫日期: 2012.04.10 2012.5.8 指导教师: 蔡逢煌 目 录1、课程设计目的22、课程设计题目和实现目标23、设计方案34、Proteus仿真原理图55、程序流程图56、程序代码57、调试总结358、设计心得体会359、参考文献351、课程设计目的MCS-51单片机课程设计是与MCS51单片机课程相配套的实践教学环节。MCS51单片机是一门实践性很强的专业基础课,通过课程设计,达到进一步理解单片机的硬件、软件和综合应用方面的知识,培
2、养实践能力和综合应用能力,开拓学习积极性、主动性,学会灵活运用已经学过的知识,并能不断接受新的知识。培养大胆发明创造的设计理念,为今后就业打下良好的基础。通过课程设计,掌握以下知识和技能:1 单片机应用系统的总体方案的设计;2 单片机应用系统的硬件设计;3 单片机应用系统的软件程序设计;4 单片机开发系统的应用和调试能力 2、课程设计题目和实现目标 2.1课程设计题目.智能电子钟设计 要求:1.能正确显示日期、时间,并且可修该; 2.具有闹铃的功能; 3、秒表功能; 4、数码显示当前温度; 2.2实现目标使用时钟芯片ds1302实现对时间、日期的计时功能。使用lcd1602液晶显示屏来显示时钟
3、芯片内部的计时情况。同时闹钟、温度显示、秒表功能也使用液晶屏显示。最终实现的效果是显示屏第一行显示年月日和星期,第二行显示小时、分钟、秒,以及温度值。在经行闹钟设置时,闹钟显示在显示屏第二行,同样秒表功能也显示在第二行。正常时间、闹钟和秒表三个功能通过按键切换,分别显示于显示屏第二行。闹钟通过闹钟程序实现,当所设闹钟与计时时间相同时,蜂鸣器发出滴滴声。秒表的设计是通过使用芯片内部定时器0作为计时时基,结合中断程序和按键实现秒表启动、停止和清零的效果。温度测量使用芯片ds18b20,读出的温度在lcd上显示,且具有实时显示测量的功能。能实现显示两位的正温度,并可以在程序内部设置一个温度最大值,当
4、所测温度超过最大值时,LED小灯闪亮以作为报警提示。3、设计方案设计的总体思路是时钟芯片1302的数据采集出来以后送入单片机,经过转码以后再送入lcd液晶屏显示。同理18b20所测量的温度通过但数据线送入单片机,经过转码以后送入显示屏,与时间日期同时显示在显示屏上。具体的设计方案如下:1602由两行每行十六个显示点阵组成,有八根数据传输线,三根控制线分别为选通位RS,使能位E,读状态位WR。另外还需外接电源线和地线。在操作过程中首先要注意的一点是由于只有一根指令传输的接线,因此指令数据是一位一位经行传输的。在对显示屏经行操作时,首先要对显示屏经行初始化,设置基本参数。之后再程序中经行操作就可以
5、只写控制字和数据。每显示一个数据都需要先给出数据要显示的地址,之后再传输数据。对显示屏经行写指令操作时要保持RS低电平RW低电平、E高脉冲。而在写入数据时要保持RS高电平、RW低电平、E高脉冲。将时钟芯片里的每一位数据送入单片机内部寄存器ACC中的地位,然后每取一位数据ACC左移一位,这样去除一个八位数据为一次读取时间。同样向时钟芯片送数据时也是通过将要写入的内容先存入ACC然后每次写入地位数据,写完一位就右移一位。初始化完成后,每次与时钟芯片通信都先写入要通信的地址,再读写数据。从时钟芯片中读出或者写入的数据是BCD码,因此需要有一个转码过程。这里我在写入数据时设计了一个十六进制数转为BCD
6、码的程序“bcd()”,转码完成后可以使用一个传输写入的程序writeto1302来写入数据,而读出时,在读出程序readfrom1302中直接加入了BCD转十六进制的语句。转码结束后数据存入数组time以便经行进一步的处理。因为lcd显示的是ASC码,且每一位显示一个数字,因此这里要对十六进制数分离并变成ASC码的相应值。与上述过程相对的是,在每次修改时间的时候,因为此时始终芯片还在工作,因此这个时候需要先停止读入时钟值,我在程序中通过设置一个标志位flag来实现控制,判断标志位的值来控制时间数据的读入。同时在更改数据结束后需要先将更改的结果送入到时钟芯片中,此过程相当于对时钟芯片再次赋值,
7、然后时钟芯片就会在所赋值的基础上继续工作,这样就达到了我们想要的修改时间的效果。对于温度的处理类似于时间的处理。温度芯片18b20也只有一条数据线,因此使用时间传输时同样的方式,每次读写八位数据组成一字节的数据。通过阅读温度测量芯片的数据手册,可以发现温度转化完成后从芯片中读出两个字节的数据,两字节数据组成了十六位的温度数字值。该值中高五位表示温度的正负,第四位表示温度的小数值。因为在我设计的程序中我只要求显示两位的正温度值,因此这里我将高四位和第四位舍去然后重新组合为一个八位数据,用上边叙述过的同样的方法处理此八位数据然后送入lcd经行显示。闹钟功能,在这里我定义了三个变量,通过对此三个变量
8、的设置,然后将变量与存储着从时钟芯片中读出的时分秒数据经行对比,当两者相同时,将接有蜂鸣器的引脚置高,再通过一个循环程序时的蜂鸣器发出滴滴的声音。秒表功能我是用到了单片机内部计时器T0和中断功能。用以前曾经写过的方法,让程序每50MS中断一次并在中断程序中经行循环,当到达一秒时秒位加一。并结合键盘设置有秒表开秒表关和秒表清零功能。键盘作为整个程序的主要操作点,设有留个独立键盘。K1为位选功能,选中要修改的位;K2是增值功能,是算选中的值加一;K3是减值功能;K4是正常时钟、闹钟、秒表切换的功能位;K5在普通模式下表示闹钟开关,在秒表模式下作为秒表的开关;K6为秒表模式下的清零位,只有在秒表停止
9、时才能动作。4、Proteus仿真原理图 5、程序流程首先程序开始运行后,可以按下K1键选择要操作的位。每次按下会换一个操作位,位顺序为:秒、分、时、日、月、年、星期。选中星期后,再次按下K1键后程序回到正常运行模式。在选中每一位的时候可以通过K2、K3键来增减数值,内部已经设置好,因此分秒只能在0到59增减变化,时的范围是0到23,而日期则与月份值有关,有大小月份之分。按下K4键后第二行显示全零,此时为闹钟设置模式,依然用K1选中位,K2K3增减数值,K5控制闹钟开启和关闭。再次按下K4键进入秒表模式,此时按下K5秒表开始运转,再次按下K5秒表停止。在秒表停止的情况下按下K6,秒表清零。程序
10、内设置温度报警值为35度,当温度高过该值后小灯会闪烁报警。闹钟时间到以后蜂鸣器发出滴滴的声音。6、程序代码#include#include#define uchar unsigned char#define uint unsigned intsbit SCLK=P36; /时钟芯片端口设置sbit IO=P34;sbit CE=P35;sbit ACC0=ACC0; /定义ACC寄存器中的第1位sbit ACC7=ACC7; /定义ACC寄存器中的第八位sbit LCDE=P26; /液晶显示控制端口设置sbit LCDRS=P25;sbit LCDWR=P24;sbit DQ=P37;sbi
11、t BF=P07;sbit K1=P20; /独立按键端口设置,modesbit K2=P21; /addsbit K3=P22; /subtractionsbit K4=P23;sbit K5=P30;sbit K6=P31;sbit LED=P27;sbit ring=P32; /alarm pinuchar table= 2012-05-01 MON;uchar table1= 00:00:00;uchar code table2=32,29,32,31,32,31,32,32,31,32,31,32;char table3=MON TUE WEN THU FRI SAT SUN; ch
12、ar time=0x00,0x00,0x00,0x01,0x05,0x06,0x0c;uchar LED_DIS=0,0,0,0,0,0,0,0;uchar LED_DIS1=0,0,0,0,0,0,0,0;uchar K1_num,flag,temph,templ,timee,K4_num,K5_num;uchar temp,T,c_miao,c_fen,c_shi,count;char shi,fen,miao;void delay(uint);void ds1302display();/*NOT USE DIRECTLYvoid writebyte(uchar ucDa)uchar i=
13、0;ACC=ucDa;for(i=8;i0;i-)IO=ACC0;SCLK=1;_nop_();SCLK=0;_nop_();ACC=ACC1;uchar readbyte(void)uchar i=0;for(i=8;i0;i-)ACC=ACC1;ACC7=IO;SCLK=1;_nop_();SCLK=0;_nop_();return(ACC);/*void writeto1302(uchar addr,uchar dat)CE=0;SCLK=0;CE=1;writebyte(addr);_nop_();_nop_();writebyte(dat); /tips the code type
14、of dat is bcdSCLK=1; CE=0;uchar readfrom1302(uchar addr)uchar dat1,temp;CE=0;SCLK=0;CE=1;writebyte(addr);_nop_();_nop_();dat1=readbyte();CE=0;temp=_cror_(dat1&0xf0,4);dat1=temp*10+(dat1&0x0f)*10/10;return(dat1); /将读出的BCD码转为十六进制码/*lcd read&writebit BusyTest() bit result;LCDRS=0; /根据规定,RS为低电平,RW为高电平时,
15、可以读状态 LCDWR=1; LCDE=1; /E=1,才允许读写 _nop_(); /空操作 _nop_(); _nop_(); _nop_(); /空操作四个机器周期,给硬件反应时间 result=BF; /将忙碌标志电平赋给result LCDE=0; /将E恢复低电平 return result;void write_com(uchar com)while(BusyTest()=1);LCDRS=0;LCDWR=0;LCDE=0;P0=com;delay(5);LCDE=1;delay(5);LCDE=0;void write_data(uchar dat)while(BusyTest
16、()=1);LCDRS=1;LCDWR=0;LCDE=0;P0=dat;delay(5);LCDE=1;delay(5);LCDE=0;/*/*void bcd() /bcd转码 uint i,tmp; for(i=0;i7;i+) tmp=timei/10; timei=timei%10; timei=timei+tmp*16; void writetime() writeto1302(0x8e,0x00);/清清除写保护 writeto1302(0x80,time0);/秒 writeto1302(0x82,time1);/分 writeto1302(0x84,time2);/时 writ
17、eto1302(0x86,time3);/日 writeto1302(0x88,time4);/月 writeto1302(0x8a,time5);/星期 writeto1302(0x8c,time6);/年 writeto1302(0x8e,0x80);/写保护 不允许写入void readtime() time6=readfrom1302(0x8d); time5=readfrom1302(0x8b); time4=readfrom1302(0x89); time3=readfrom1302(0x87); time2=readfrom1302(0x85); time1=readfrom13
18、02(0x83); time0=readfrom1302(0x81);void into() LED_DIS0=time2/10+0x30; LED_DIS1=time2%10+0x30; LED_DIS2=:; LED_DIS3=time1/10+0x30; LED_DIS4=time1%10+0x30; LED_DIS5=:; LED_DIS6=time0/10+0x30; LED_DIS7=time0%10+0x30; LED_DIS10=time6/10+0x30; LED_DIS11=time6%10+0x30; LED_DIS12=-; LED_DIS13=time4/10+0x3
19、0; LED_DIS14=time4%10+0x30; LED_DIS15=-; LED_DIS16=time3/10+0x30; LED_DIS17=time3%10+0x30;/*/*keyscanvoid write_lcdline_1(uchar addr,uchar dat) /sfmuchar shiwei,gewei;shiwei=dat/10;gewei=dat%10;write_com(0x80+addr);write_data(0x30+shiwei);write_data(0x30+gewei);void write_lcdline_2(uchar addr,uchar
20、dat)/sfmuchar shiwei,gewei;shiwei=dat/10;gewei=dat%10;write_com(0x80+0x40+addr);write_data(0x30+shiwei);write_data(0x30+gewei);void keyscan()if(K6=0)delay(5);if(K6=0)while(!K6);if(K4_num=2)&(K5_num=0)write_lcdline_2(7,0);write_lcdline_2(4,0);write_lcdline_2(1,0);c_miao=0;c_fen=0;c_shi=0;if(K5=0)dela
21、y(5);if(K5=0)K5_num+;while(!K5);if(K5_num=2)K5_num=0;if(K4=0)uint tmp;uchar s,f,m;delay(5);if(K4=0)K4_num+;while(!K4);flag=1;s=time2;f=time1;m=time0;if(K4_num=1)uchar i;write_com(0x80+0x40);for(i=0;i9;i+)write_data(table1i);if(K4_num=2)uchar i;write_com(0x80+0x40);for(i=0;i9;i+)write_data(table1i);i
22、f(K4_num=3)K4_num=0;tmp=m/10; m=m%10; m=m+tmp*16;tmp=f/10; f=f%10; f=f+tmp*16;tmp=s/10; s=s%10; s=s+tmp*16;writeto1302(0x8e,0x00);/清清除写保护 writeto1302(0x80,m);/秒 writeto1302(0x82,f);/分 writeto1302(0x84,s);/时flag=0;if(K1=0)delay(5);if(K1=0)K1_num+;flag=1;while(!K1);if(K1_num=1)write_com(0x80+0x40+7);w
23、rite_com(0x0f); /开显示,显示光标,光标闪烁 if(K1_num=2)write_com(0x80+0x40+4);if(K1_num=3)write_com(0x80+0x40+1);if(K1_num=4)write_com(0x80+9);if(K1_num=5)write_com(0x80+6);if(K1_num=6)write_com(0x80+3);if(K1_num=7)write_com(0x80+12);if(K1_num=8)K1_num=0;bcd();writetime();write_com(0x0c); /关光标,关光标闪烁flag=0;if(K1
24、_num!=0)if(K2=0)delay(5);if(K2=0)while(!K2);if(K1_num=1)if(K4_num=0)time0+;if(time0=60)time0=0;write_lcdline_2(7,time0);write_com(0x80+0x40+7);if(K4_num=1)miao+;if(miao=60)miao=0;write_lcdline_2(7,miao);write_com(0x80+0x40+7);if(K1_num=2)if(K4_num=0)time1+;if(time1=60)time1=0;write_lcdline_2(4,time1
25、);write_com(0x80+0x40+4);if(K4_num=1)fen+;if(fen=60)fen=0;write_lcdline_2(4,fen);write_com(0x80+0x40+4);if(K1_num=3)if(K4_num=0)time2+;if(time2=24)time2=0;write_lcdline_2(1,time2);write_com(0x80+0x40+1);if(K4_num=1)shi+;if(shi=24)shi=0;write_lcdline_2(1,shi);write_com(0x80+0x40+1);if(K1_num=4)time3+
26、;if(time3=table2time4-1)time3=1;write_lcdline_1(9,time3);write_com(0x80+9);if(K1_num=5)time4+;if(time4=13)time4=1;write_lcdline_1(6,time4);write_com(0x80+6);if(K1_num=6)time6+;if(time6=99)time6=0;write_lcdline_1(3,time6);write_com(0x80+3);if(K1_num=7)time5+;if(time5=7)time5=0;if(time5=0)write_com(0x
27、80+12);write_data(table3time5);write_data(table3time5+1);write_data(table3time5+2);if(time5=1)write_com(0x80+12);write_data(table34);write_data(table35);write_data(table36);if(time5=2)write_com(0x80+12);write_data(table38);write_data(table39);write_data(table310);if(time5=3)write_com(0x80+12);write_
28、data(table312);write_data(table313);write_data(table314);if(time5=4)write_com(0x80+12);write_data(table316);write_data(table317);write_data(table318);if(time5=5)write_com(0x80+12);write_data(table320);write_data(table321);write_data(table322);if(time5=6)write_com(0x80+12);write_data(table324);write_
29、data(table325);write_data(table326);write_com(0x80+12);if(K3=0)delay(5);if(K3=0)while(!K3);if(K1_num=1)if(K4_num=0)time0-;if(time0=-1)time0=59;write_lcdline_2(7,time0);write_com(0x80+0x40+7);if(K4_num=1)miao-;if(miao=-1)miao=59;write_lcdline_2(7,miao);write_com(0x80+0x40+7);if(K1_num=2)if(K4_num=0)t
30、ime1-;if(time1=-1)time1=59;write_lcdline_2(4,time1);write_com(0x80+0x40+4);if(K4_num=1)fen-;if(fen=-1)fen=59;write_lcdline_2(4,fen);write_com(0x80+0x40+4);if(K1_num=3)if(K4_num=0)time2-;if(time2=-1)time2=23;write_lcdline_2(1,time2);write_com(0x80+0x40+1);if(K4_num=1)shi-;if(shi=-1)shi=23;write_lcdli
31、ne_2(1,shi);write_com(0x80+0x40+1);if(K1_num=4)time3-;if(time3=0)time3=(table2time4-1-1);write_lcdline_1(9,time3);write_com(0x80+9);if(K1_num=5)time4-;if(time4=0)time4=12;write_lcdline_1(6,time4);write_com(0x80+6);if(K1_num=6)time6-;if(time6=-1)time6=99;write_lcdline_1(3,time6);write_com(0x80+3);if(
32、K1_num=7) /星期设置time5-;if(time5=-1)time5=6;if(time5=0)write_com(0x80+12);write_data(table3time5);write_data(table3time5+1);write_data(table3time5+2);if(time5=1)write_com(0x80+12);write_data(table34);write_data(table35);write_data(table36);if(time5=2)write_com(0x80+12);write_data(table38);write_data(t
33、able39);write_data(table310);if(time5=3)write_com(0x80+12);write_data(table312);write_data(table313);write_data(table314);if(time5=4)write_com(0x80+12);write_data(table316);write_data(table317);write_data(table318);if(time5=5)write_com(0x80+12);write_data(table320);write_data(table321);write_data(table322);if(time5=6)write_com(0x80+12);write_data(table324);write_data(table325);write_data(table326);write_com(0x80+12);/*/*temprature chip 18b20bit init18b20() bit flag; /储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在 DQ = 1; /先将数据线拉高 for(timee=0;timee2;timee+); /略微延时约6微秒 DQ = 0; /再将数据线