51单片机课设(电子钟)
更新时间:2023-09-23 17:55:01 阅读量: IT计算机 文档下载
福州大学
《MCS-51单片机》
课程设计
题 目: 数字时钟
姓 名:
学 号:
学 院: 电气工程与自动化学院
专 业: 电机电器 年 级: 2009
起讫日期: 2012.04.10 ~2012.5.8
指导教师: 蔡逢煌
目 录
1、课程设计目的................................................................................ 2 2、课程设计题目和实现目标 ............................................................. 2 3、设计方案 ....................................................................................... 3 4、Proteus仿真原理图 ....................................................................... 5 5、程序流程图 ................................................................................... 5 6、程序代码 ....................................................................................... 5 7、调试总结 ..................................................................................... 35 8、设计心得体会.............................................................................. 35 9、参考文献 ..................................................................................... 35
1
1、课程设计目的
《MCS-51单片机》课程设计是与《MCS-51单片机》课程相配套的实践教学环节。《MCS-51单片机》是一门实践性很强的专业基础课,通过课程设计,达到进一步理解单片机的硬件、软件和综合应用方面的知识,培养实践能力和综合应用能力,开拓学习积极性、主动性,学会灵活运用已经学过的知识,并能不断接受新的知识。培养大胆发明创造的设计理念,为今后就业打下良好的基础。
通过课程设计,掌握以下知识和技能: 1. 单片机应用系统的总体方案的设计; 2. 单片机应用系统的硬件设计; 3. 单片机应用系统的软件程序设计; 4. 单片机开发系统的应用和调试能力
2、课程设计题目和实现目标 2.1课程设计题目 .智能电子钟设计
要求:1.能正确显示日期、时间,并且可修该; 2.具有闹铃的功能; 3、秒表功能;
4、数码显示当前温度; 2.2实现目标
使用时钟芯片ds1302实现对时间、日期的计时功能。
使用lcd1602液晶显示屏来显示时钟芯片内部的计时情况。同时闹钟、温度显示、秒表功能也使用液晶屏显示。最终实现的效果是显示屏第一行显示年月日和星期,第二行显示小时、分钟、秒,以及温度值。在经行闹钟设置时,闹钟显示在显示屏第二行,同样秒表功能也显示在第二行。正常时间、闹钟和秒表三个功能通过按键切换,分别显示于显示屏第二行。
闹钟通过闹钟程序实现,当所设闹钟与计时时间相同时,蜂鸣器发出滴滴声。 秒表的设计是通过使用芯片内部定时器0作为计时时基,结合中断程序和按键实现秒表启动、停止和清零的效果。
2
温度测量使用芯片ds18b20,读出的温度在lcd上显示,且具有实时显示测量的功能。能实现显示两位的正温度,并可以在程序内部设置一个温度最大值,当所测温度超过最大值时,LED小灯闪亮以作为报警提示。 3、设计方案
设计的总体思路是时钟芯片1302的数据采集出来以后送入单片机,经过转码以后再送入lcd液晶屏显示。同理18b20所测量的温度通过但数据线送入单片机,经过转码以后送入显示屏,与时间日期同时显示在显示屏上。
具体的设计方案如下:
1602由两行每行十六个显示点阵组成,有八根数据传输线,三根控制线分别为选通位RS,使能位E,读状态位WR。另外还需外接电源线和地线。
在操作过程中首先要注意的一点是由于只有一根指令传输的接线,因此指令数据是一位一位经行传输的。在对显示屏经行操作时,首先要对显示屏经行初始化,设置基本参数。之后再程序中经行操作就可以只写控制字和数据。每显示一个数据都需要先给出数据要显示的地址,之后再传输数据。对显示屏经行写指令操作时要保持RS低电平RW低电平、E高脉冲。而在写入数据时要保持RS高电平、RW低电平、E高脉冲。
将时钟芯片里的每一位数据送入单片机内部寄存器ACC中的地位,然后每取一位数据ACC左移一位,这样去除一个八位数据为一次读取时间。同样向时钟芯片送数据时也是通过将要写入的内容先存入ACC然后每次写入地位数据,写完一位就右移一位。初始化完成后,每次与时钟芯片通信都先写入要通信的地址,再读写数据。
从时钟芯片中读出或者写入的数据是BCD码,因此需要有一个转码过程。这里我在写入数据时设计了一个十六进制数转为BCD码的程序“bcd()”,转码完成后可以使用一个传输写入的程序writeto1302来写入数据,而读出时,在读出程序readfrom1302中直接加入了BCD转十六进制的语句。
转码结束后数据存入数组time[]以便经行进一步的处理。因为lcd显示的是ASC码,且每一位显示一个数字,因此这里要对十六进制数分离并变成ASC码的相应值。
与上述过程相对的是,在每次修改时间的时候,因为此时始终芯片还在工作,因此这个时候需要先停止读入时钟值,我在程序中通过设置一个标志位flag来实现控制,判断标志位的值来控制时间数据的读入。同时在更改数据结束后需要先将更改的结果送入到时钟芯片中,此过程相当于对时钟芯片再次赋值,然后时钟芯片就会在所赋值的基础
3
上继续工作,这样就达到了我们想要的修改时间的效果。
对于温度的处理类似于时间的处理。温度芯片18b20也只有一条数据线,因此使用时间传输时同样的方式,每次读写八位数据组成一字节的数据。通过阅读温度测量芯片的数据手册,可以发现温度转化完成后从芯片中读出两个字节的数据,两字节数据组成了十六位的温度数字值。该值中高五位表示温度的正负,第四位表示温度的小数值。因为在我设计的程序中我只要求显示两位的正温度值,因此这里我将高四位和第四位舍去然后重新组合为一个八位数据,用上边叙述过的同样的方法处理此八位数据然后送入lcd经行显示。
闹钟功能,在这里我定义了三个变量,通过对此三个变量的设置,然后将变量与存储着从时钟芯片中读出的时分秒数据经行对比,当两者相同时,将接有蜂鸣器的引脚置高,再通过一个循环程序时的蜂鸣器发出滴滴的声音。
秒表功能我是用到了单片机内部计时器T0和中断功能。用以前曾经写过的方法,让程序每50MS中断一次并在中断程序中经行循环,当到达一秒时秒位加一。并结合键盘设置有秒表开秒表关和秒表清零功能。
键盘作为整个程序的主要操作点,设有留个独立键盘。K1为位选功能,选中要修改的位;K2是增值功能,是算选中的值加一;K3是减值功能;K4是正常时钟、闹钟、秒表切换的功能位;K5在普通模式下表示闹钟开关,在秒表模式下作为秒表的开关;K6为秒表模式下的清零位,只有在秒表停止时才能动作。
4
LCDE=0; P0=dat; delay(5); LCDE=1; delay(5); LCDE=0; }
//********************* //********************** void bcd() {
uint i,tmp; for(i=0;i<7;i++) {tmp=time[i]/10; time[i]=time[i]; time[i]=time[i]+tmp*16; } }
void writetime() {
writeto1302(0x8e,0x00);//清清除写保护 writeto1302(0x80,time[0]);//秒 writeto1302(0x82,time[1]);//分 writeto1302(0x84,time[2]);//时 writeto1302(0x86,time[3]);//日 writeto1302(0x88,time[4]);//月 writeto1302(0x8a,time[5]);//星期 writeto1302(0x8c,time[6]);//年
writeto1302(0x8e,0x80);//写保护 不允许写入
10
//bcd转码
}
void readtime() {
time[6]=readfrom1302(0x8d); time[5]=readfrom1302(0x8b); time[4]=readfrom1302(0x89); time[3]=readfrom1302(0x87); time[2]=readfrom1302(0x85); time[1]=readfrom1302(0x83); time[0]=readfrom1302(0x81); }
void into() {
LED_DIS[0]=time[2]/10+0x30; LED_DIS[1]=time[2]+0x30; LED_DIS[2]=':';
LED_DIS[3]=time[1]/10+0x30; LED_DIS[4]=time[1]+0x30; LED_DIS[5]=':';
LED_DIS[6]=time[0]/10+0x30; LED_DIS[7]=time[0]+0x30; LED_DIS1[0]=time[6]/10+0x30; LED_DIS1[1]=time[6]+0x30; LED_DIS1[2]='-';
LED_DIS1[3]=time[4]/10+0x30; LED_DIS1[4]=time[4]+0x30; LED_DIS1[5]='-';
LED_DIS1[6]=time[3]/10+0x30; LED_DIS1[7]=time[3]+0x30; }
11
//**************************** //****************************keyscan void write_lcdline_1(uchar addr,uchar dat) //sfm {
uchar shiwei,gewei; shiwei=dat/10; gewei=dat; write_com(0x80+addr); write_data(0x30+shiwei); write_data(0x30+gewei); }
void write_lcdline_2(uchar addr,uchar dat)//sfm {
uchar shiwei,gewei; shiwei=dat/10; gewei=dat;
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)) {
12
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) { delay(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;
13
s=time[2]; f=time[1]; m=time[0]; if(K4_num==1) { uchar i;
write_com(0x80+0x40); for(i=0;i<9;i++) { write_data(table1[i]);
}
}
if(K4_num==2) { uchar i;
write_com(0x80+0x40); for(i=0;i<9;i++) { write_data(table1[i]); }
}
if(K4_num==3) {
K4_num=0; tmp=m/10; m=m;
m=m+tmp*16; tmp=f/10; f=f;
f=f+tmp*16;
14
}
}
}
tmp=s/10;
s=s; 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);
write_com(0x0f); //开显示,显示光标,光标闪烁
if(K1_num==2) { }
if(K1_num==3) {
15
write_com(0x80+0x40+4);
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_num!=0) {
//关光标,关光标闪烁
16
if(K2==0) {
delay(5); if(K2==0) {
while(!K2); if(K1_num==1) { }
if(K1_num==2) {
if(K4_num==0) {
time[1]++;
17
if(K4_num==0) { }
if(K4_num==1) { }
miao++; if(miao==60)
miao=0; time[0]++; if(time[0]==60)
time[0]=0;
write_lcdline_2(7,time[0]); write_com(0x80+0x40+7);
write_lcdline_2(7,miao); write_com(0x80+0x40+7);
}
}
if(time[1]==60)
time[1]=0;
write_lcdline_2(4,time[1]); 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) { }
if(K4_num==1) {
shi++; if(shi==24)
shi=0; time[2]++; if(time[2]==24)
time[2]=0;
write_lcdline_2(1,time[2]); write_com(0x80+0x40+1);
write_lcdline_2(1,shi);
18
}
}
write_com(0x80+0x40+1);
if(K1_num==4) { }
if(K1_num==5) { }
if(K1_num==6) { }
if(K1_num==7) {
time[5]++;
19
time[3]++;
if(time[3]==table2[time[4]-1])
time[3]=1;
write_lcdline_1(9,time[3]); write_com(0x80+9);
time[4]++; if(time[4]==13)
time[4]=1;
write_lcdline_1(6,time[4]); write_com(0x80+6);
time[6]++; if(time[6]==99)
time[6]=0;
write_lcdline_1(3,time[6]); write_com(0x80+3);
7、调试总结
通过调试,在仿真条件下满足所涉及的要求,达到了预期的设想。
在调试过程中,通过摸索,感受到,将程序写成一个一个的模块更有利于调试。可以对每个模块功能经行单独调试,这样就能够准确地定位问题可能出现的位置,有利于程序的修改。 8、设计心得体会
通过此次单片机课程设计,我取得了很多经验。首先,我学会了如何阅读器件的数据手册。在设计时很重要的一点就是学习使用一些芯片器件,因此对于数据手册的阅读和学习十分必要。通过这次设计我的经验是阅读数据手册首先要初步了解芯片的工作过程皆为时序图。要了解芯片的初始化程序有哪些内容,芯片在工作时如何对其经行操作。其次就是要了解到芯片的数据格式,比如本次设计中用到的1302芯片,其数据为BCD码。另外还有了解芯片如何与单片机本身经行联系产生联系。做到此三点,一个芯片的基本功能就可以利用起来了。
第二点,通过此次课设,我对于调试程序也有了一定的心得认识。我更加深刻地意识到了模块化程序的必要性和便捷之处。通过将程序分函数书写,使得主程序内容非常简练,并且使得主函数里的程序结构十分明确,优化了整个程序的结构和逻辑联系。另外一点,模块化的函数程序对于程序一步一步的调试有着巨大的意义,大幅降低了程序调试的难度,更加便于寻找程序错误点。
第三点是在写程序之前应该构建一个大概的程序流程,脑子里有一个简单的结构,明确每一个功能通过怎样的方式来实现。这个总体的结构对于一个程序的顺利书写是非常重要的。
第四点是通过之前一些练习熟悉了一些写程序的惯用写法和技巧,这对于书写程序中避免错误大有裨益。同时在出现错误时,通过软件编译的提示能很快反应出来错误的类型,并很快找到错误。
参考文献
[1] DS1302数据手册. [2] DS18B20数据手册. [3]LCD1602数据手册.
35
if(time[5]==7)
time[5]=0;
if(time[5]==0) { }
if(time[5]==1) { }
if(time[5]==2) { }
if(time[5]==3) { }
20
write_com(0x80+12); write_data(table3[time[5]]); write_data(table3[time[5]+1]); write_data(table3[time[5]+2]);
write_com(0x80+12); write_data(table3[4]); write_data(table3[5]); write_data(table3[6]);
write_com(0x80+12); write_data(table3[8]); write_data(table3[9]); write_data(table3[10]);
write_com(0x80+12); write_data(table3[12]); write_data(table3[13]); write_data(table3[14]);
}
}
}
if(time[5]==4) { }
if(time[5]==5) { }
if(time[5]==6) { }
write_com(0x80+12);
write_com(0x80+12); write_data(table3[24]); write_data(table3[25]); write_data(table3[26]); write_com(0x80+12); write_data(table3[20]); write_data(table3[21]); write_data(table3[22]); write_com(0x80+12); write_data(table3[16]); write_data(table3[17]); write_data(table3[18]);
if(K3==0) {
delay(5); if(K3==0) {
21
while(!K3); if(K1_num==1) { }
if(K1_num==2) {
if(K4_num==0) { }
22
if(K4_num==0) { }
if(K4_num==1) { }
miao--; if(miao==-1)
miao=59; time[0]--; if(time[0]==-1)
time[0]=59;
write_lcdline_2(7,time[0]); write_com(0x80+0x40+7);
write_lcdline_2(7,miao); write_com(0x80+0x40+7);
time[1]--; if(time[1]==-1)
time[1]=59;
write_lcdline_2(4,time[1]); 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(K1_num==4) {
23
if(K4_num==0) { }
if(K4_num==1) { }
shi--; if(shi==-1)
shi=23; time[2]--; if(time[2]==-1)
time[2]=23;
write_lcdline_2(1,time[2]); write_com(0x80+0x40+1);
write_lcdline_2(1,shi); write_com(0x80+0x40+1);
}
time[3]--; if(time[3]==0)
time[3]=(table2[time[4]-1]-1);
write_lcdline_1(9,time[3]); write_com(0x80+9);
if(K1_num==5) { }
if(K1_num==6) { }
if(K1_num==7) //星期设置 {
time[5]--; if(time[5]==-1)
time[5]=6; time[6]--; if(time[6]==-1)
time[6]=99; time[4]--; if(time[4]==0)
time[4]=12;
write_lcdline_1(6,time[4]); write_com(0x80+6);
write_lcdline_1(3,time[6]); write_com(0x80+3);
if(time[5]==0) {
write_com(0x80+12);
24
正在阅读:
51单片机课设(电子钟)09-23
华为的国际化之路及人力资源管理03-10
英语基础模块上册I12单元教案06-28
沈阳市人力资源和社会保障局劳动关系管理信息系统操作手册(企业用)08-31
污水厂毕业设计终稿_secret05-11
《面朝大海春暖花开》学本08-05
2018年华东师大版数学七年级下册第一次月考测试卷及答案05-04
建筑识图试题11-09
健康与财富英语作文02-05