电子时钟实训报告
一, 实训目的 二,实训要求 三,实训基本原理 四,实训设计分析 五,实训要求实现 A.电路设计 1. 整体设计 2. 分块设计 B.程序设计 1 程序总体设计 2全部完整代码: 六.实训总结及感想
一,实训目的 20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。 现代生活的人们越来越重视起了时间观念,可以说是时间和金钱划上了等号。对于那些对时间把握非常严格和准确的人或事来说,时间的不准确会带来非常大的麻烦,所以电子钟是以其小巧,价格低廉,走时精度高,使用方便,功能多,便于集成化而受广大消费的喜爱,得到了广泛的使用。 1. 学习8051定时器时间计时处理、按键扫描及LCD液晶显示的设计方法。 2. 设计任务及要求 利用实训平台上LCD1602液晶显示屏, 设计带有闹铃功能的数字时钟
二,实训要求
A.基本要求: 1. 在LCD1602液晶显示屏上显示当前日期,时间。 2. 利用按键可对时间及闹玲进行设置,并可显示设置闹玲的时间。闹玲时间到蜂鸣器发出声响,一分钟后闹铃停止。
B.扩展部分: 1.日历功能(能对年,月,日,星期进行显示,分辨平年,闰年以及各月天数,并调整)实现年月日时分秒的调整,星期准确的随着日期改变而改变进行显示。 2.定时功能(设定一段时间长度,定时到后,闹铃提示)
C.可扩展部分: 1.闹铃重响功能(闹铃被停止后,以停止时刻开始,一段时间后闹铃重响,且重响时间的间隔可调) 2.可进行备忘录提示,按照年月日,可在设定的某年某月进行闹铃提示。
三,实训基本原理
四,实训设计分析 针对要实现的功能,采用AT89S52单片机进行设计,AT89S52 单片机是一款低功耗,高性能CMOS8位单片机,片内含4KB在线可编程(ISP)的可反复擦写1000次的Flash只读程序存储器,器件采用高密度、非易失性存储技术制造,兼容标准MCS- 51指令系统及80C51引脚结构。这样,既能做到经济合理又能实现预期的功能。 在程序方面,采用分块设计的方法,这样既减小了编程难度、使程序易于理解,又能便于添加各项功能。程序可分为闹钟的声音程序、时间显示程序、日期显示程序,秒表显示程序,时间调整程序、闹钟调整程序、定时调整程序,延时程序等。运用这种方法,关键在于各模块的兼容和配合,若各模块不匹配会出现意想不到的错误。 首先,在编程之前必须了解硬件结构尤其是各引脚的用法,以及内部寄存器、存储单元的用法,否则,编程无从下手,电路也无法设计。这是前期准备工作。第二部分是硬件部分:依据想要的功能分块设计设计,比如输入需要开关电路,输出需要显示驱动电路和数码管电路等。第三部分是软件部分:先学习理解C语言的编程方法再根据设计的硬件电路进行分块的编程调试,最终完成程序设计。第四部分是软件画图部分:设计好电路后进行画图,包括电路图和仿真图的绘制。第五部分是软件仿真部分:软硬件设计好后将软件载入芯片中进行仿真,仿真无法完成时检查软件程序和硬件电路并进行修改直到仿真成功。第六部分是硬件实现部分:连接电路并导入程序检查电路,若与设计的完全一样一般能实现想要的功能。最后进行功能扩展,在已经正确的设计基础上,添加额外的功能! 五,实训要求实现 A.电路设计 1. 整体设计 此次设计主要是应用单片机来设计电子时钟,硬件部分主要分以下电路模块:显示电路用lcd1602显示,年份,月份,星期,小时、分钟和秒(日),使电路更加简单。单片机采用AT89S51系列,这种单片机应用简单,适合电子钟设计。 电路的总体设计框架如下:
2. 分块设计 模块电路主要分为:复位电路、按键、LCD和时钟芯片。 2.1 按键处理模块 按键处理设置为:如没有按键,则时钟正常走时。当按K0键一次,时钟暂停走动进入调小时状态,再按K0键一次,进入调分状态,再按K0键一次,回到正常走时;对于K1和K2按键,如果是正常走时,按K1和K2不起作用,如果进入调时或调分状态,按K1可对时或分进行加1操作,小时加到24则回到0,分加到60则回到0;按K2可对时或分进行减1操作,小时减到负则回到23,分减到负则回到59。按键处理模块流程如图所示。 2.2 输出部分 本电路的输出信号LCD的写入命令和写入数据,闹铃脉冲信号。 闹铃由P1.5端输出,模块如下: 日期时间由LCD1602输出,模块如下: 2.3 晶振与复位电路 本实训单片机时钟用内部时钟,模块如下: 复位电路为手动复位构成,模块如下:
B.程序设计 B.1 程序总体设计 软件程序划分为以下几个部分:系统主程序、DS1302驱动程序、LCD驱动程序。在主程序中调用DS1302驱动程序和LCD驱动程序,另外在主程序中还包含按键处理。 主程序先是将LCD初始化,其次在LCD显示日期和时间的提示信息,然后进入死循环,在循环中先判断是否有键按下,如按下K0键,则功能单元加1;如按下K1键,则根据功能单元的内容把日期时间相应位加1;如按下K2键,则根据功能单元的内容把日期时间相应位减1;并把修改后的日期时间写入1302(在这个过程中注意日期时间的数据格式的转换)。其次读DS1302日历时钟寄存器,读出的内容存入日期、时间缓冲区;最后把日期、时间缓冲区数转化为ASCII码放入LCD显示缓冲区并调用LCD显示程序显示。 程序总的流程图如下:
C.硬件定时液晶显示时钟硬件电路
2.全部完整代码: 基于STC89S51单片机以及液晶1602显示的万年历项目
六.实训总结及感想 时光飞逝,一转眼,一个学期又进尾声了,本学期的单片机综合课程设计也在三周内完成了。
俗话说“好的开始是成功的一半”。说起课程设计,我认为最重要的就是做好设计的预习,认真的研究老师给的题目。其次,老师对实验的讲解要认真听讲,把资料认真看懂,因为只有都明白了,做起设计就会事半功倍,如果没弄明白,就迷迷糊糊的去做设计,到头来一点收获也没有。最后,最重要的是要重视程序的模块化,能看懂程序,在此基础上扩展功能,也要注重程序的调试,掌握其方法。
虽然这次的课程设计算起来在实验室的时间只有六个课时,不过在宿舍里查资料,看资料,做实验的时间一定不止六个课时。
硬件的设计跟焊接都要我们自己动手去焊,软件的编程也要我们不断的调试,最终一个能完成课程设计的劳动成果出来了,很高兴它能按着设计的思想与要求运动起来。
当然,这其中也有很多问题,第一、不够细心比如由于粗心大意焊错了线,由于对课本理论的不熟悉导致编程出现错误。第二,是在学习态度上,这次课设是对我的学习态度的一次检验。对于这次单片机综合课程实习,我的第一大心得体会就是作为一名工程技术人员,要求具备的首要素质绝对应该是严谨。我们这次实习所遇到的多半问题多数都是由于我们不够严谨。第三,在做人上,我认识到,无论做什么事情,只要你足够坚强,有足够的毅力与决心,有足够的挑战困难的勇气,就没有什么办不到的。 我们组一起完成了这次单片机课程设计课题中的电子时钟设计,从中学到很多东西,如何从理论到实践中的转化,怎样将所学的知识运用到实践当中,运用到现实生活当中,此次的课堂设计给我奠定了基础,我会在以后的工作学习中磨练自己,使自己适合于以后的竞争,同时在查找资料的过程中学到许多新的知识, 在和同学合作的过程中增进友谊,一个团队合作的重要性,也是使我对团队精神的积极进取性与重要性有了更加充分的理解。 最后,感谢老师的一个学期对我们的教育,正是老师的精彩课程和对我们严格的要求,老师热心的帮助,使得我们课程设计能够顺利的完成,同时在课程设计的过程中巩固我们的单片机知识,相信对我以后的工作会有很大的帮助!
单片机源程序如下: - #include <reg51.h>
- #include <absacc.h> //定义绝对地址访问
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit T_CLK = P1^3; //DS1302时钟线引脚
- sbit T_IO = P1^4; //DS1302数据线引脚
- sbit T_RST = P1^2; //DS1302复位线引脚
- sbit RS=P1^7; //定义LCD的控制线
- sbit RW=P1^6;
- sbit EN=P1^5;
- sbit key0=P3^0; //定义按键
- sbit key1=P3^1;
- sbit key2=P3^2;
- sbit ACC7 =ACC^7;
- sbit ACC0 =ACC^0;
- char line1[]="LCD test program";
- char line2[]="Everything is OK";
- char line3[]="Welcome to you ";
- char line4[]="Welcome to using";
- void init_LCD(void);
- void write_inst(char); // 写入指令函数
- void write_char(char); // 写入字元函数
- void check_BF(void); // 检查忙碌函数
- void delay1ms(int);
- uchar datechar[]={"DATE:"};
- uchar timechar[]={"TIME:"};
- uchar datebuffer[8]={0,0,0x2d,0,0,0x2d,0,0}; //定义日历显示缓冲区
- uchar timebuffer[8]={0,0,0x3a,0,0,0x3a,0,0}; //定义时间显示缓冲区
- uchar data ttime[3]={0x00,0x00,0x00}; //分别为秒、分和小时的值
- uchar data tdata[3]={0x00,0x00,0x00}; //分别为年、月、日
- //往DS1302写入1Byte数据
- void WriteB(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;
- }
- }
- //从DS1302读取1Byte数据
- uchar ReadB(void)
- {
- uchar i;
- for(i=8; i>0; i--)
- {
- ACC = ACC >>1;
- ACC7 = T_IO;T_CLK = 1;T_CLK = 0; //相当于汇编中的 RRC
- }
- return(ACC);
- }
- //DS1302单字节写,向指定单元写命令/数据,ucAddr: DS1302地址, ucDa: 要写的命令/数据
- void v_W1302(uchar ucAddr,uchar ucDa)
- {
- T_RST = 0;
- T_CLK = 0;
- _nop_();_nop_();
- T_RST = 1;
- _nop_();_nop_();
- WriteB(ucAddr); /* 地址,命令 */
- WriteB(ucDa); /* 写1Byte数据*/
- T_CLK = 1;
- T_RST =0;
- }
- //DS1302单字节读,从指定地址单元读出的数据
- uchar uc_R1302(uchar ucAddr)
- {
- uchar ucDa=0;
- T_RST = 0;T_CLK = 0;
- T_RST = 1;
- WriteB(ucAddr); /*写地址*/
- ucDa = ReadB(); /*读1Byte命令/数据 */
- T_CLK = 1;T_RST =0;
- return(ucDa);
- }
- //LCD检查忙函数
- void fbusy()
- {
- P2 = 0xff;
- RS = 0;
- RW = 1;
- EN = 1;
- EN = 0;
- while((P2 & 0x80))
- {
- EN = 0;
- EN = 1;
- }
- }
- //LCD写命令函数
- void wc51r(uchar j)
- {
- fbusy();
- EN = 0;
- RS = 0;
- RW = 0;
- EN = 1;
- P2 = j;
- EN = 0;
- }
- //LCD写数据函数
- void wc51ddr(uchar j)
- {
- fbusy(); //读状态;
- EN = 0;
- RS = 1;
- RW = 0;
- EN = 1;
- P2 = j;
- EN = 0;
- }
- void init() //LCD1602初始化
- {
- while(1)
- { //指定第一行位置
- write_inst(0x80);
- for(j=0;j<16;j++)
- write_char(line1[j]); //循环显示16个字符
- write_inst(0xc0); //指定第二行位置
- for(j=0;j<16;j++)
- write_char(line2[j]); //循环显示16个字符
- delay1ms(2000); //延时2s (STC89C51:2000)(MPC82G516:20000)
- write_inst(0x80);
- for(j=0;j<16;j++)
- write_char(line3[j]);
- write_inst(0xc0);
- for(j=0;j<16;j++)
- write_char(line4[j]);
- delay1ms(2000);
- }
- }
- void init_LCD(void)
- {
- write_inst(0x38); //指令6:设定两行
- //write_inst(0x08); //指令4:关闭显示
- wc51r(0x01); //清屏
- wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型
- wc51r(0x0c); //显示器开,光标开,字符不闪烁
- wc51r(0x06); //字符不动,光标自动右移一格
- }
- //************延时函数************
- void delay(uint i) //延时函数
- {uint y,j;
- for (j=0;j<i;j++){
- for (y=0;y<0xff;y++){;}}
- }
- void main(void)
- {
- uchar i,set;
- uchar data temp;
- SP=0X50;
- delay(10);
- init();
- wc51r(0x80);
-
- for (i=0;i<5;i++) wc51ddr(datechar[i]); //第一行开始显示DATA:
- wc51r(0xc0);
- for (i=0;i<5;i++) wc51ddr(timechar[i]); //第二行开始显示TIME:
- while(1)
- {P3=0XFF;
- if(key0==0) { delay(10);if (key0==0) { while (key0==0); set++; if
- (set==6) set=0;}}
- if(key1==0) { delay(10); //如果是加1键,则日历、时钟相应位加1
- if (key1==0) { while (key1==0);
- switch(set)
- {
- case 1: tdata[0]++;if (tdata[0]==100) tdata[0]=0;
- temp=(tdata[0]/10)*16+tdata[0]%10;
- v_W1302(0x8e,0);
- v_W1302(0x8c,temp);
- v_W1302(0x8e,0x80);
- break;
- case 2: tdata[1]++;if (tdata[1]==13) tdata[1]=1;
- temp=(tdata[1]/10)*16+tdata[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x88,temp);
- v_W1302(0x8e,0x80);
- break;
- case 3: tdata[2]++;if (tdata[2]==32) tdata[2]=1;
- temp=(tdata[2]/10)*16+tdata[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x86,temp);
- v_W1302(0x8e,0x80);
- break;
- case 4: ttime[2]++;if (ttime[2]==24) ttime[2]=0;
- temp=(ttime[2]/10)*16+ttime[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x84,temp);
- v_W1302(0x8e,0x80);
- break;
- case 5: ttime[1]++;if (ttime[1]==60) ttime[1]=0;
- temp=(ttime[1]/10)*16+ttime[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x82,temp);
- v_W1302(0x8e,0x80);
- break;
- }
- }
- }
- if(key2==0) { delay(10); //如果是减1键,则日历、时钟相应位减1
- if (key2==0) { while (key2==0);
- switch(set)
- {
- case 1: tdata[0]--;if (tdata[0]==0xff) tdata[0]=99;
- temp=(tdata[0]/10)*16+tdata[0]%10;
- v_W1302(0x8e,0);
- v_W1302(0x8c,temp);
- v_W1302(0x8e,0x80);
- break;
- case 2: tdata[1]--;if (tdata[1]==0x00) tdata[1]=12;
- temp=(tdata[1]/10)*16+tdata[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x88,temp);
- v_W1302(0x8e,0x80);
- break;
- case 3: tdata[2]--;if (tdata[2]==0x00) tdata[2]=31;
- temp=(tdata[2]/10)*16+tdata[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x86,temp);
- v_W1302(0x8e,0x80);
- break;
- case 4: ttime[2]--;if (ttime[2]==0xff) ttime[2]=23;
- temp=(ttime[2]/10)*16+ttime[2]%10;
- v_W1302(0x8e,0);
- v_W1302(0x84,temp);
- v_W1302(0x8e,0x80);
- break;
- case 5: ttime[1]--;if (ttime[1]==0xff) ttime[1]=59;
- temp=(ttime[1]/10)*16+ttime[1]%10;
- v_W1302(0x8e,0);
- v_W1302(0x82,temp);
- v_W1302(0x8e,0x80);
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
|