第一篇:长沙理工大学《单片机课程设计》电子钟单片机实习报告
目录
一
引言...............................................................................................................................5
二
硬件设计.......................................................................................................................5
三
软件设计.......................................................................................................................5
四
调试过程及问题分析.................................................................................................6
五
结论.............................................................................................................................7
六
参考文献.....................................................................................................................7
附件.....................................................................................................................................8
一 引言
单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及我们生活中广泛使用的各种智能IC卡、电子宠物等,单片机都起到了举足轻重的作用。
所以单片机技术也日趋成熟。单片机是集CPU,RAM,ROM,定时,计数和多种接口于一体的微控制器。它体积小,成本低,功能强。而52系列单片机是各单片机中最为典型和最有代表性的一种。
此次单片机原理及应用实习通过利用52单片机对电子钟的设计,从而达到学习、了解单片机相关指令在各方面的应用,以及初步了解开发软、硬件的知识。
二 硬件设计
本次单片机原理及应用实习我们组用到的硬件为MCS51开发板和一个LCD12864液晶显示器。
在MCS51开发板中,对于我们组做数字电子钟而言应用到ds1302芯片,蜂鸣器,LED点阵显示屏,STC89S52单片机,锁存器等等硬件设备。
通过对这些硬件的使用实现我们组规定的以及我们拓展的要求。
三 软件设计
此次基于单片机的电子钟的实习基本要求为:
基本要求
(1)能通过键盘设定年月日时分秒;
(2)在LCD12864上显示年月日时分秒及星期;(3)整点蜂鸣器响6次,每秒响一次,最后一响是整点;(4)按学校的作息时间表定时打铃(可用一个LED灯模拟打铃)扩展要求
自动计算和显示阴历
基于这些功能,我们用到了如下程序
(1)时钟程序ds1302(2)按键控制程序keyscan
(3)整点报时程序fengming(4)作息时间表程序schooltime fengming(5)显示程序LCD12864(6)自动计算阴历程序 Chinesecalender(7)自动计算星期程序conver_week 我们最初的整体思路是将我们的实习课题分成几个模块,每个人负责一个部分,争取第一周弄完个人部分.第二周主要进行不同模块的整合,以及整个程序的调试和改进.此外准备答辩的PPT,由组长答辩。
程序设计流程图如下:
四 调试过程及问题分析
在这一次单片机原理及应用的实习中,我学到了很多。虽然整个过程并不是一帆风顺的,但是通过
我们的共同努力,最终完成了任务。充分发挥了团队精神,我们互帮互助,共同提高。
我觉得在拿到一个课题的时候,我们首先应该思考的是干什么?然后才是怎么干?最后是如何优化。于是我开始上网搜有关电子钟设计的相关资料,我了解到:我们本次是利用MCS51开发板和LCD12864液晶显示器制作的,可以完成计时、计分、几秒和校时、校分的功能。微处理器是单片机的核心,完成运算和控制的操作串行口数据存储器与复位电路、时钟电路、校时电路由微处理器控制完成各自的任务。最后通过液晶显示器显示时分秒。
在这次实习中我负责的是显示程序LCD12864,刚开始我对于LCD显示程序并不是太了解。在校园网上找到了些相关的初步显示程序。通过LCD12864中的一些程序的调用,才能进行显示,但那是以图片的形式显示的,与我们所期望的显示还是有一定的差别,所以我又做进一步的修改,通过和组员的讨论,我才知道有一个显示汉字的程序是通过字模软件实现的,之后我们的显示这一块就可以依据我们自己的想法进行设计了。
而在整个的程序综合中,也遇到了一些问题。比如在阴历显示在屏幕上的时候,最初只显示阴历两个字,不显示具体的阴历,后来经过检查发现程序调用出现问题,改正后继续进行优化。
就这样,我们反复的修改调试,最终完成了我们的整个课程设计。
五 结论
在本次的课程设计中,我们虽然走了些小弯路,但是通过我们的共同努力,最终完成了任务。我从中我学到了很多,比如团队协作精神,众人拾材火焰高。任何大问题,在一步一步细化之后,解决起来就轻松得多了!我相信只要付出了就会有收获。无论什么事情,只有当你用心去做了之后你才会发现它的真实意义所在。我觉得这一次实习是非常有意义的,不仅提高了专业素养,还培养了我们的合作精神。我要把握每一次学习的机会,认真对待,为以后的就业及更深层次的发展添砖加瓦。
六 参考文献
一、谭浩强 C语言课程设计(第三版)清华大学出版社 2005.7
二、杨恢先 黄辉先 单片机原理及应用[M] 北京人民邮电出版社 2006.10
三、C编写组编 常用C语言速查手册 龙门书局 1995
附件
*********************************初始化LCD*******************************/ void Lcminit(void){ cbyte=DISPOFF;
WrL(cbyte);
WrR(cbyte);
cbyte=DISPON;
WrL(cbyte);
WrR(cbyte);
cbyte=DISPFIRST;
WrL(cbyte);
WrR(cbyte);
Lcmcls();
Locatexy(0,0);} /***********************************LCD清屏********************************/ void Lcmcls(void){ uchar i,j;
for(i=0;i<8;i++){
delay(6);
for(j=0;j delay(6); Wrdata(0x0,i,j); } } } /************************************写左区*********************************/ void WrL(uchar x){ P0=0xFF;//P0口送FF,准备读 lck = 0; P1 = 0x2a;//ELCD=1/W=1(读),CSB=1,CSA=0 lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00;//ELCD=0,R/W=0(读),CSB=0,CSA=0 lck = 1; P0 = x; //数据送到P0口 lck = 0; P1 = 0x22;//ELCD=1,RW = 0(写),CSB=1,CSA=0 lck = 1; lck = 0; P1 = 0x00;//ELCD=0,RW = 0(写),CSB=0,CSA=0 lck = 1;} /***********************************写右区***********************************/ void WrR(uchar data x){ P0=0xFF;//P0口送FF,准备读 lck = 0; P1 = 0x29;//ELCD=1,R/W=1(读),CSB=0,CSA=1 lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00;//ELCD=0,R/W=0(读),CSB=0,CSA=1 lck = 1; P0=x; //数据送到P0口 lck = 0; P1 = 0x21;//ELCD=1,RW = 0(写),CSB=0,CSA=1 lck = 1;lck = 0;P1 = 0x00;//ELCD=0,RW = 0(写),CSB=0,CSA=0 lck = 1; } /**********************************显示定位***********************************/ void Locatexy(uchar row,uchar col){ uchar x, y, right; switch(col&0xc0) { case 0:{ P0=0xFF;//P0口送FF,准备读 lck = 0; P1 = 0x29;//ELCD=1,R/W=1(读),CSB=0,CSA=1 lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00; lck = 1; right = 1;break;}//置右半屏标志 case 0x40:{ P0=0xFF;//P0口送FF,准备读 lck = 0; P1 = 0x2a;//ELCD=1,R/W=1(读),CSB=1,CSA=0 lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00;//ELCD=0,R/W=0(读)CSB=0,CSA=0 lck = 1; right = 0;break;}//置左半屏标志 } x=col&0x3f|SETX;//把列数据变成行命令 y=row&0x07|SETY;//把行数据变成行命令 /****************************************************************************/ lck = 0; if(right) P1 = 0x29; else P1 = 0x2a; lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00; lck = 1;/***********************************以上为判断忙标志**************************/ P0 = y; lck = 0; if(right) P1 = 0x21; else P1 = 0x22; lck = 1; lck = 0; P1 = 0x00; lck = 1;/************************************以上为送行命令*****************************/ P0=0xFF; lck = 0; if(right) P1 = 0x29; else P1 = 0x2a; lck = 1; while(P0 & LCDBUZY);//最高位为1,表示忙,则循环 lck = 0; P1 = 0x00; lck = 1;/*************************************以上为判断忙标志***************************/ P0 = x; lck = 0; if(right) P1 = 0x21; else P1 = 0x22; lck = 1; lck = 0; P1 = 0x00; lck = 1;/*************************************以上为送列命令***************************/ if(right) statu = 1; else statu = 0;//置左又半区标志 } /*************************************数据写输出*******************************/ void Wrdata(uchar x,uchar row,uchar col){ Locatexy(row,col);//定位显示位置 lck = 0; if(statu) P1 = 0x05;//ELCD=0R/W=0(写),D/I= 1,CSB=0,CSA=1 else P1 = 0x06;//ELCD=0,R/W=0(写),D/I= 1,CSB=1,CSA=0 lck = 1; P0 = x; lck = 0; if(statu) P1 = 0x25;//ELCD=1,R/W=0(写),D/I= 1,CSB=0,CSA=1 else P1 = 0x26;//ELCD=1,R/W=0(写),D/I= 1,CSB=1,CSA=0 lck = 1; lck = 0; P1 = 0x00; lck = 1;} /**********************************半角数据点阵输出******************************/ void Puthalf(uchar *strch,uchar row,uchar col){ uchar i,bakerx; bakerx = row; for(i=0;i<16;i++)//上半字输出 { cbyte=strch[i]; Wrdata(cbyte,bakerx,col); cbyte=strch[i+1]; Wrdata(cbyte,bakerx+1,col); col++; i++;} } void Puthz(uchar *str,uchar row,uchar col){ uchar i,bakerx; bakerx=row; for(i=0;i<32;i++) { cbyte=str[i]; Wrdata(cbyte,row,col); //上半字节输出 i++; row=bakerx+1; cbyte=str[i]; Wrdata(cbyte,row,col); //下半字节输出 row=bakerx; col=col+1; } } /****************************字符型点阵行--》列转换************************/ void VtoH8x16change(uchar *hzbuf){ uchar i,j,k, cash[16]; uchar newbyte, savebit[8]; for(k=0;k<16;k++){ newbyte = 0; for(i=0;i<8;i++){ savebit[i]=hzbuf[i] & 0x80;} for(j=0;j<8;j++){ savebit[j] = savebit[j] >>(7-j); newbyte = newbyte | savebit[j];} cash[k] = newbyte; newbyte = 0; for(i=8;i<16;i++){ savebit[i-8]=hzbuf[i] & 0x80;} for(j=0;j<8;j++){ savebit[j] = savebit[j] >>(7-j); newbyte = newbyte |savebit[j];} cash[k+1] = newbyte; for(j=0;j<16;j++){ hzbuf[j] = hzbuf[j] <<1; } k++;} for(i=0;i<16;i++) hzbuf[i] = cash[i];} /*******************************显示英文和符号字符*******************************/ void vWrite8x16Character(uchar *ch,uchar row,uchar col,bit flag){uchar ucXArray[16],i; if(flag){ // 反白显示英文 for(i = 0;i < 16;i++) ucXArray[i] = ~ch[i];}else{ for(i = 0;i < 16;i++) ucXArray[i] = ch[i];} VtoH8x16change(ucXArray);Puthalf(ucXArray,row,col);} /****************************显示中英文字符串************************************/ void vWrite8x16String(uchar *str,uchar row, uchar col, bit flag){ /************************v_RTInputByte*************************/ void v_RTInputByte(uchar ucDa){ uchar i;ACC = ucDa;for(i=8;i>0;i--){ T_IO = ACC0;/*相当于汇编中的 RRC */ T_CLK = 1;T_CLK = 0;ACC = ACC >> 1;} } /********************** uchar uc_RTOutputByte*************************/ uchar uc_RTOutputByte(void){ uchar i;for(i=8;i>0;i--){ ACC = ACC >>1;/*相当于汇编中的 RRC */ ACC7 = T_IO;T_CLK = 1;T_CLK = 0;} return(ACC);} /************************v_W1302 *************************************/ void v_W1302(uchar ucAddr, uchar ucDa){ lck = 0;P1 = 0x00;lck = 1;unsigned char i, j,thiscol;j = strlen(str);for(i = 0;i < j;i++){ thiscol =(i % 16)* 8 + col;//计算列地址 if(str[i] < 0xa1)//当前显示内容为英文字符 vWrite8x16Character(&char_Table[str[i]-0x20][0],row,thiscol,flag); }} T_CLK = 0; lck = 0;P1 = 0x10;lck = 1;v_RTInputByte(ucAddr);/* 地址,命令 */ v_RTInputByte(ucDa);/* 写1Byte数据*/ T_CLK = 1;lck = 0;P1 = 0x00;lck = 1;} /**************************uc_R1302***********************************/ uchar uc_R1302(uchar ucAddr){ uchar ucDa; lck = 0;P1 = 0x00;lck = 1; T_CLK = 0; lck = 0;P1 = 0x10;lck = 1;v_RTInputByte(ucAddr);/* 地址,命令 */ ucDa = uc_RTOutputByte();/* 读1Byte数据 */ T_CLK = 1;lck = 0;P1 = 0x00;lck = 1;return(ucDa);} /************************* v_Set1302 *********************************/ void v_Set1302(uchar *pSecDa){ uchar i;uchar ucAddr = 0x80; v_W1302(0x8e,0x00);/* 控制命令,WP=0,写操作?*/ for(i =7;i>0;i--){ v_W1302(ucAddr,*pSecDa);/* 秒 分 时 日 月 星期 年 */ pSecDa++;ucAddr +=2;} v_W1302(0x8e,0x80);/* 控制命令,WP=1,写保护?*/ } /*******************************v_Get1302**************************************/ void v_Get1302(uchar ucCurtime[]){ uchar i;uchar ucAddr = 0x81;for(i=0;i<7;i++){ ucCurtime[i] = uc_R1302(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */ ucAddr += 2;delay(100);} } /**********************************屏幕显示*********************************/ void pingmu(){ uchar disp,copymt; uchar temp; copymt = 0xff; P0=0xff; v_Get1302(&buffer);//读取DS1302 Conver_week(0,buffer[6],buffer[4],buffer[3]);Chinesecalender(0,buffer[6],buffer[4],buffer[3]);disp = buffer[0] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],2,100,0);//秒个位 temp =buffer[0] & 0x7f;temp = temp/16;disp = temp%10 + '0';vWrite8x16Character(&char_Table[disp-0x20][0],2,92,0);//秒十位 copymt = buffer[1]; disp = buffer[1] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],2,68,0);//分个位 temp =buffer[1] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],2,60,0);//分十位 disp = buffer[2] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],2,30,0);//时个位 temp =buffer[2] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],2,22,0);//时十位 disp = buffer[3] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,100,0);//日个位 temp =buffer[3] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,92,0);//日十位 disp = buffer[4] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,68,0);//月个位 temp =buffer[4] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,60,0);//月十位 disp = buffer[6] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,30,0);//年个位 temp =buffer[6] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,22,0);//年十位 disp = buffer[7] % 0x10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,14,0);//年百位 temp =buffer[7] & 0x7f; temp = temp/16; disp = temp%10 + '0'; vWrite8x16Character(&char_Table[disp-0x20][0],0,6,0);//年千位 } 课程设计任务书 (指导教师填写) 课程设计名称电子技术课程设计学生姓名专业班级设计题目数字钟 一、课程设计的任务和目的任务:设计一台能显示“时”、“分”、“秒”的数字钟,周期为24小时;具有校时、正点报时功能。 目的:培养学生综合运用所学知识的能力,综合设计能力,培养动手能力及分析问题、解决问题的能力。 二、设计内容、技术条件和要求 1.数字钟可显示“时”、“分”、“秒”,且“时”、“分”、“秒”分别用两个数码管显示,计满23小时60分钟60秒,则全部清零。 2.具有校时功能,时、分校时用1HZ的信号进行,而秒较时用2HZ时钟信号进行。 3.整点能自动报时。要求报时声响为四低一高,最后一响为整点,前四声用500HZ信号让喇叭发声,最后一声用1000HZ信号。 4.根据上述要求,画出电路总框图,简述各部分工作原理。 5.进行各部分电路的设计,要求有分析过程、原理图表示。 6.对原理图进行仿真。 7.在实验箱上组装、调试。 8.撰写设计总结报告。 三、时间进度安排 第一周:理论设计。 周一上午布置设计任务,讲解设计要求,安排答疑、实验时间; 周三、周四下午课程设计答疑,其他时间学生查资料,做初步理论设计; 周五交设计初稿,由指导教师审查; 第二周:仿真和安装调试、撰写设计总结报告 周一、二学生进实验室做仿真实验,并根据实验情况修正设计图; 周三至周五做插接线实验,最后根据实验情况总结、撰写设计说明书。 四、主要参考文献 1.各种版本的数字电子技术基础教材 2.各种版本的电子技术课程设计指导书 3.集成电路手册 指导教师签字:年月日 单片机课程设计 题目 专业 通信工程 班级 11级1班 学号 姓名 电 子 钟 设 计 单片机原理与应用课程设计 电子钟设计 功能要求: 1、设计一个电子时钟,要求可以显示时、分、秒,用户可以设置时间。 2、实现秒表功能。 功能描述 (1) 时钟。初始界面是时钟显示,按键S1是调时选位,按键S2是加数。根据不同的闪烁位置进行调节。 (2) 年与日,星期。在初始状态下,按下S2,则跳转,显示年月日,5S后跳回初始界面。若在年月日界面再次按下S2,则再次跳转,显示星期,几秒后跳转回初始界面。 (3) 秒表。在初始界面下,按下S3,则跳转,进入秒表。秒表功能键如下:S1 退出秒表;S2 停止开始计时;S3 秒表清零。 (4) 闹钟。在设置中设置好时间,最高位设为“1”则打开闹钟。最高位设为“0”则关闭闹钟。在闹钟响是,按S3进行关闹钟。 工作原理 硬件 采用80C51系列单片机作为CPU,P0口作为数据线,通过锁存器进行段选和位选,是数码管不断地显示数字。数码管的显示是扫描式。(1) 本电子钟用的单片机型号是STC89C516RD+。P0口作为段选和位选的数据线。P10口为段选寄存器的使能端。P11口为位选寄存器的使能端。晶振采用的12MHz晶振。要求频率稳定。 (2) 本电子钟用的是共阴极数码管。从左到右,第1,2位是秒位;第4,5位是分位;第7,8位是时位。第3,6位是“--”。 (3) 通过单片机的P0口,先对数码管进行位选,即在位锁存器使能是将P0口数据进行锁存。再通过段锁存器将P0口送来的段数据进行锁存。此时数码管的第一位显示数字。同样的步骤进行第二位显示。以非常快的速度进行,由于人眼的余辉效应,会看到8位数码管一起亮。即可以显示时间。通过单片机的内部TO,T1的计数。即可以实现时钟,秒表等功能。(4)电路图如下: 软件 程序代码包括三部分:1.bujian(部件库)2.main(主函数)3.H(头文件库)。一 .bujian(部件库)(1)xianshi.c #include //数码管秒个位 P0=t[s%10];p11=0;P0=0xff;delay(m);p10=1;p10=0;p11=1;P0=0xbf;p11=0; //消隐 P0=t[s/10]; //消隐 //数码管秒十位 P0=0xff;delay(m);} void led_f(unsigned int s){ p10=1;// P0=t[s%10];p10=0;p11=1;P0=0xef; p11=0; P0=0xff;delay(m);p10=1; P0=t[s/10];p10=0;p11=1;P0=0xf7;p11=0; P0=0xff;delay(m);} void led_h(unsigned int s){ // p10=1;P0=t[s%10];p10=0;p11=1;P0=0xfd; p11=0;// P0=0xff;delay(m);p10=1; P0=t[s/10];p10=0;p11=1;P0=0xfe;p11=0; 数码管分个位 //消隐 //数码管分十位 //消隐 数码管时个位 消隐 //数码管时十位 //消隐 P0=0xff;delay(m);} void line(void){ p10=1;P0=0x40;p10=0;p11=1;P0=0xfb;delay(m);p11=0; p10=1;P0=0x40;p10=0;p11=1;P0=0xdf;p11=0;delay(m);} //消隐 P0=0xff; //数码管“---” //消隐 P0=0xff; //数码管“---” (2)miaobiao.c #include #include { while(!s3){led_s(mms);led_f(ms);line();led_h(mf);} TR1=0;mms=0;ms=0;mf=0;} } } (3)Delay.c #include void delay(unsigned int a) { unsigned char l; while(a--) {for(l=0;l<100;l++);} } (4)gongneng.c #include #include if(s2==0){ delay(3);if(s2==0)while(!s2){ led_s(s);delay(1);line();led_f(f);delay(1);led_h(h);delay(1);} // while(1){ led_s(r);delay(2);led_f(y);delay(2);line();led_h(nian);delay(2);aa++;if(s2==0) { while(!s2) { led_s(r);delay(1);line();led_f(y);delay(1);led_h(nian);delay(1);} //星期显示 while(1) {led_f(xing);delay(2); bb++; if(bb==100){bb=0;break;} 日期显示 } } if(aa==100) line();led_f(y);delay(1);led_h(nian);delay(1); } } if(s1==0){ delay(3);if(s1==0){ switch(x){ case 1 : if(shanshuo==1){led_s(s);} line();led_f(f);delay(2);led_h(h);delay(2);break;case 2 :led_s(s);if(shanshuo==1){led_f(f);} delay(2);line();led_h(h);delay(2);break;case 3 : led_s(s);led_f(f);delay(2);line();if(shanshuo==1){led_h(h);} delay(2);break;case 4 : if(shanshuo==1){led_s(r);} led_f(y);delay(2);line();led_h(nian);delay(2);break;case 5 : led_s(r);if(shanshuo==1){led_f(y);} delay(2);line();led_h(nian);delay(2);break;case 6 :led_s(r);led_f(y);delay(2);line();if(shanshuo==1){led_h(nian);} delay(2);break;case 7 :if(shanshuo==1){led_f(xing);delay(5);} break;case 8 :if(shanshuo==1){led_s(nf);} line();led_f(nh);delay(2);led_h(ns);delay(2);break;case 9 :led_s(nf);if(shanshuo==1){led_f(nh);} delay(2);line();led_h(ns);delay(2);break;case 10:led_s(nf);led_f(nh);delay(2);line();if(shanshuo==1){led_h(ns);} delay(2);break;default : break;} aa++;if(s2==0){ while(!s2){if(x==1||x==2||x==3){ led_s(s);delay(1);line();led_f(f);delay(1);led_h(h);delay(1);} if(x==4||x==5||x==6){ led_s(r);delay(1);line();led_f(y);delay(1);led_h(nian);delay(1);} if(x==7){ led_f(xing);} if(x==8||x==9||x==10){led_s(nf);led_f(nh);delay(2);line();led_h(ns);delay(2);} } switch(x) { case 1 : s++;if(s>59)s=0;break; while(!s1);while(1) { if(x==1||x==2||x==3)TR0=0;else TR0=1;if(aa==20){shanshuo=!shanshuo;aa=0;} { break;} { led_s(r);delay(1); } if(s1==0) case 2 : } f++;if(f>59)f=0;break; case 3 : h++;if(h>23)h=0;break;case 4 : r++;if(r>31)r=1;break;case 5 : y++;if(y>12)y=1;break;case 6 : case 7 : nian++;if(nian>20)nian=10;break;xing++;if(xing>7)xing=1;break; case 8 : nf++;if(nf>59)nf=0;break;case 9 : nh++;if(nh>23)nh=0;break;case 10: ns=!ns;break; default: break;{while(!s1){if(x==1||x==2||x==3){ led_s(s);delay(1);line();led_f(f);delay(1);led_h(h);delay(1);} if(x==4||x==5||x==6){ led_s(r);delay(1);line();led_f(y);delay(1);led_h(nian);delay(1);} if(x==7){ led_f(xing);} if(x==8||x==9||x==10){led_s(nf);led_f(nh);delay(2);line();led_h(ns);delay(2);} } x++;if(x>10){ x=0;TR0=1;break;} } } } } } } 二.H(头文件库)(1)Delay.h #ifndef _DELAY_H__ void led_s(unsigned int s);void led_h(unsigned int s);#define _DELAY_H__ void delay(unsigned int a);#endif(2)xianshi.h #ifndef _XIANSHI_H__ #define _XIANSHI_H__ void led_f(unsigned int s);void line(void);#endif(3)gongneng.h #ifndef _DONGNENG_H__ #define _GONGNENG_H__ void gongneng(void);#endif(4)miaobiao.h #ifndef _MIAOBIAO_H__ #define _MIAOBIAO_H__ void miaobiao(void);#endif(5)dingyi.h #ifndef _DINGYI_H__ #define _DINGYI_H__ sbit s1=P2^4; sbit s2=P2^5; sbit s3=P2^6;sbit p10=P1^0;sbit p11=P1^1;sbit p12=P1^2;#endif //流水灯使能端 //按键1 //按键2 //按键3 sbit p37=P3^7;//蜂鸣器时能 三.Main(主函数)(1)main.c #include ET0=1;TH0=6;TR0=1; //关闭流水灯 ET1=1;TH1=(65535-5000)/256;TL1=(65535-5000)%256;TR1=0;while(1){ if((s3==0)&&(ns==0)){while(!s3);miaobiao();} if(s1==0||s2==0)gongneng();else { led_s(s);line();led_f(f);line();led_h(h);} if((f==nf)&&(h==nh)&&(ns==1))ll=1;else ll=0;} } void zhongduan(void)interrupt 1 { if((ll==1)&&(ns==1)) { p37=!p37;if((s3==0)&&(ns==1)){ while(!s3)ns=0;p37=1;} } n++;if(n==5000){n=0;s++;if(s==60){ s=0;f++;} if(f==60){ f=0;h++;} if(h==24){ h=0;r++;xing++;} switch(r){ case 29 : if(nian/4==0){if(y==2)r=0;} y++;case 31 : if(y==4||y==6||y==9||y==11){ } if(xing>7)xing=1;if(y==13){ y=1;nian++;} } } default : break; break;case 30 : if((nian/4)!=0){if(y==2){ r=0;y++;}} break; r=0;y++;} break;case 32 : if(y==1||y==3||y==5||y==7||y==8||y==10||y==12){r=0;y++;} break;void zhongduan1(void)interrupt 3 { TH1=(65535-5000)/256; m++;TL1=(65535-5000)%256;if(m==2){mms++;m=0;if(mms>=100){ mms=0;ms++;} if(ms==60){ ms=0;mf++;} if(mf==60){ mf=0;} } } 参考文献: 单片机中级教程(第2版)、单片机语言C51程序设计(赵文博)感想: 这次课程设计整体来说是成功的,但我也发现了自己许多错漏和不足之处。譬如,最简单的程序没写好就想着写更复杂的程序,做事还是缺乏耐性和细心,当有时遇到问题时,总觉得无从下手,对于课本上的知识不能很好的组织起来。在编写各功能程序时,特别是后来增添的比较复杂的程序 ORG0000H LJMPMAIN ORG001BH LJMPLOOP ORG0100H MAIN:MOV21H,#17H MOV22H,#3AH MOV23H,#00H;设定时间初值 MOV36H,#10 MOV39H,#10 MOVR7,#14H;循环20次50*20=1000msMOVDPTR,#0F003H MOVA,#10000000B;8255命令口地址MOVX@DPTR,A MOVTMOD,#10H MOVTH1,#3CH MOVTL1,#0B0H;设定计时初值 MOVIE,#88H;设定中断运行位 SETBTR1 LOP:LCALLSTART LCALLDSN;调用显示程序 LJMPLOP LOOP:MOVTH1,#3CH;重装时间初值 MOVTL1,#0B0H DJNZR7,LOOP1;循环结束 MOVR7,#14H INC23H MOVA,23H CJNEA,#3CH,LOOP1 MOV23H,#00H INC22H MOVA,22H CJNEA,#3CH,LOOP1 MOV22H,#00H INC21H MOVA,21H CJNEA,#18H,LOOP1 MOV21H,#00H MOV22H,#00H MOV23H,#00H LOOP1: RETI START: MOVR1,#21H;将小时放在两个位地址中MOVA,@R1 MOVB,#0AH DIVAB MOV3BH,A MOV3AH,B INCR1 MOVA,@R1 MOVB,#0AH DIVAB MOV38H,A MOV37H,B INCR1 MOVA,@R1 MOVB,#0AH DIVAB MOV35H,A MOV34H,B RET DSN:MOVR0,#34H;显示子程序;显示数据缓冲区首址送R0 MOVR3,#7FH;使显示器最左边位亮 LP1:MOVDPTR,#0F000H;数据指针指向A口 MOVA,R3 MOVX@DPTR,A;送扫描值 INCDPTR;数据指针指向B口MOVA,@R0;取欲显示数据的字形码表位 PUSHDPH PUSHDPL;显示查表指令地址偏移量 MOVDPTR,#TAB MOVCA,@A+DPTR;取出字形码 POPDPL POPDPH MOVX@DPTR,A;送出显示 ACALLDELAY;调用延时子程序 INCR0;指向下一个显示缓冲区地址MOVA,R3 JNBACC.0,LP2;扫描到第八个显示器? RRA;未到,扫描码右移一位 MOVR3,A AJMPLP1 LP2:RET TAB:DB0FCH,60H,0DAH,0F2H,66H,0B6H DB0BEH,0E0H,0FEH,0F6H,02H,0DFH DELAY: MOVR5,#05H;延时子程序 DL1:MOVR6,#0FFH DL2:DJNZR6,DL2 DJNZR5,DL1RET END 单片机课程设计电子钟设计 目录 一、摘要 二、设计任务 三、基本原理 数码管显示可以用静态显示或动态显示方法。静态显示需要数据锁存器等硬件,接口复杂,时钟显示用四个数码管。动态显示相对简单,但需动态扫描,扫描频率要大于人视觉暂留频率,信息看起来才稳定。译码方式可分为软件译码和硬件译码,软件译码通过译码程序查的显示信息的字段码;硬件译码通过硬件译码器得到显示信息的字段码,实际中通常采用软件译码。 在具体处理时,定时器计数器采用中断方式工作,对时钟的形成在中断服务程序中实现。在主程序中只需对定时器计数器初始化、调用显示子程序和控制子程序。另外,为了使用便,设计了简单的按键,可以通过按键实现时、分的调整,这样在主程序中就加入了按键设置子程序。 四、编程算法思路 五、程序流程图 六、硬件单元设计 七、软件单元设计 八、调试结果分析 九、设计总结及心得体会 十、参考文献 一设计任务 1、基本任务:利用定时器/计数器中断和静态显示或动态显示,实现电子时钟的时分秒精确走时和校准 。时间显示用四个数码管分别显示时、分、秒用点表示,在时和分的中间闪动,时间显示格式(18:49) 时间校准用2个键实现:一个键K1作移位选择(选中要修改的位,选中的位用闪烁指示),一个键K2做加1(对选中的位进行加1修改)。 2、功能增强型任务:在基本任务的基础上加上日历功能、准时报时功能和跑表功能 (1)日历功能:能实现时、分、秒和年、月、日计时,增加1个按键控制分3屏例如显开始的第1屏默认显示“时、分、秒”四位+秒点,按下K3键显示“月和日”四位,再按下课K3键显示“年份”四位,再按下K3键显示“时、分、秒”,依次类推。程序要能处理闰年、闰月功能。 (2)准点报时功能:可以在增加一个按键K4设计具有闹钟功能,实现定点报时。具体操作是:按下 K4键,进入闹钟设置功能,再通过K1、K2键来完成定点报警时间的设置。 (3)跑表功能:再增加一个按键K5设计跑表功能,实现启动毫秒计数,相当与田径运动比赛的跑 表工作。 三基本原理 软件时钟时利用单片机内部的定时器/计数器来实现的,它的过程如下:首先定单片机内部的一个定时器/计数器工作于定时方式,对机器周期形成基准时间,然后用另一个定时器/计数器或软件计数的方法对基准时间计数形成秒,秒计60次形成分,分计60次形成小时,小时计24次则计满一天。然后通过数码管把它们的内容在相应位置显示出来即可。 四编程算法思路 1、主程序的设计:串行口工作方式0,定时器/计数器1工作在方式1进行初始化,然后通过循环(调用显示子程序)等待定时中断的到来。 2、按键的控制:KEY1控制时的调节,kEY2控制分的调节,KEY3控制时、分定型 3、中断服务程序的设计:中断服务程序主要功能是实现时、分、秒的计时处理。 4、时、分、秒计时的实现:秒计时时采用中断方式进行溢出次数的累计得到的。从秒到分,从分到时可通过软件的累加和比较到位方法来实现。要求每满1秒,则“秒”单元中的内容加1;“秒”单元每满60,则“秒”单元清0,同时“分”单元中的内容加1;“分”单元每满60,则“分”单元清0,同时“时”单元加1。“时”单元每满24,则将“时”单元清0。 5、显示子程序:采用数码管静态显示来显示时钟的走动 6,延时子程序:用来实现按键操控延时和实现整点12时报时 五程序流程图 六硬件单元设计 1、电路总设计图 2、AT89C51芯片 七软件单元设计 1、资源分配:定时器T1,P1.6为调整时钟,P1.5为调整分钟,P1.4为控制调整 30H秒显示单元,31H分显示单元,32H时显示单元,08H放分调整标 志,09H放时调整标志,0AH放闪烁标志 2、程序清单(加注释) 八调试结果分析 在实验操作过程中,将所写好的程序打入计算机内,通过编译检查其是否有错误,如有错误将其改正,直至无误后下载仿真器,实现运行。观察实验箱上的数码管显示,判断其是否为所需结果,如果与所要求的有差别,需继续调试,重新修改程序,检查硬件设施不断地调试,不断地检查直至得到所要的结果。在调试过程中,开始运行时能够实现时钟的显示,但是无法实现其闪烁功能,后经不断调试修改及同学的帮助最终实现该功能,能够达到时钟显示调节的基本要求,还可以实现整点报时。但在增加其功能显示年月时又出现一定的问题,未能实现该功能,程序存在一定的不足性,需继续完善,实现更多的功能 九设计总结及心得体会 经过两天的单片机课程设计,终于完成了我的电子时钟的设计,虽然没有完全达到设计要求,但从心底里说,还是高兴的,毕竟这次设计把一些基本功能都做了出来,只是一些增强型功能未能实现。 在本次设计的过程中,我发现很多的问题,虽然以前还做过一些实验但这次设计真的让我长进了很多单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,要有通篇的全局思想考虑问题。在操作的过程中,出现许多错误,都是在连接处不能够上下连贯正确运行,还需继续努力。有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。 从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的写与读的过程中才能提高,这就是我在课程设计中的最大收获,同时,要把所学只是灵活应用才能真正领悟其中的意义,加深对它的理解与掌握。还有,通过此次的操作也使我的实践操作能力得到了进一步的提高。 十参考文献 【1】张毅刚,彭喜元,董继成。单片机原理及应用。北京:高等教育出版社,2003 【2】周航慈。单片机应用程序设计技术(修订版)。北京:北京航空航天大学出版社,2002 【3】万光毅等。单片机实验与实践教程。北京:北京航空航天大学出版社,2003 【4】何立民,I2C总线应用系统设计。北京:北京航空航天大学出版社,2002 【5】周航慈,朱兆优,李跃忠。智能仪器原理与设计。北京:北航大学出版社,2005第二篇:单片机课程设计电子钟
第三篇:单片机课程设计-电子钟-完整
第四篇:单片机课程设计电子钟源程序
第五篇:单片机课程设计电子钟设计