找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3268|回复: 1
打印 上一主题 下一主题
收起左侧

单片机+1302芯片电子时钟实训报告与仿真电路源码下载

[复制链接]
跳转到指定楼层
楼主
电子时钟实训报告

一, 实训目的

二,实训要求

三,实训基本原理

四,实训设计分析

五,实训要求实现

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显示的万年历项目

.实训总结及感想

时光飞逝,一转眼,一个学期又进尾声了,本学期的单片机综合课程设计也在三周内完成了。

  俗话说“好的开始是成功的一半”。说起课程设计,我认为最重要的就是做好设计的预习,认真的研究老师给的题目。其次,老师对实验的讲解要认真听讲,把资料认真看懂,因为只有都明白了,做起设计就会事半功倍,如果没弄明白,就迷迷糊糊的去做设计,到头来一点收获也没有。最后,最重要的是要重视程序的模块化,能看懂程序,在此基础上扩展功能,也要注重程序的调试,掌握其方法。

  虽然这次的课程设计算起来在实验室的时间只有六个课时,不过在宿舍里查资料,看资料,做实验的时间一定不止六个课时。

  硬件的设计跟焊接都要我们自己动手去焊,软件的编程也要我们不断的调试,最终一个能完成课程设计的劳动成果出来了,很高兴它能按着设计的思想与要求运动起来。

  当然,这其中也有很多问题,第一、不够细心比如由于粗心大意焊错了线,由于对课本理论的不熟悉导致编程出现错误。第二,是在学习态度上,这次课设是对我的学习态度的一次检验。对于这次单片机综合课程实习,我的第一大心得体会就是作为一名工程技术人员,要求具备的首要素质绝对应该是严谨。我们这次实习所遇到的多半问题多数都是由于我们不够严谨。第三,在做人上,我认识到,无论做什么事情,只要你足够坚强,有足够的毅力与决心,有足够的挑战困难的勇气,就没有什么办不到的。
我们组一起完成了这次单片机课程设计课题中的电子时钟设计,从中学到很多东西,如何从理论到实践中的转化,怎样将所学的知识运用到实践当中,运用到现实生活当中,此次的课堂设计给我奠定了基础,我会在以后的工作学习中磨练自己,使自己适合于以后的竞争,同时在查找资料的过程中学到许多新的知识, 在和同学合作的过程中增进友谊,一个团队合作的重要性,也是使我对团队精神的积极进取性与重要性有了更加充分的理解。
最后,感谢老师的一个学期对我们的教育,正是老师的精彩课程和对我们严格的要求,老师热心的帮助,使得我们课程设计能够顺利的完成,同时在课程设计的过程中巩固我们的单片机知识,相信对我以后的工作会有很大的帮助!

单片机源程序如下:
  1. #include  <reg51.h>
  2. #include  <absacc.h>       //定义绝对地址访问
  3. #include  <intrins.h>
  4. #define  uchar  unsigned  char
  5. #define  uint  unsigned  int
  6. sbit T_CLK = P1^3;     //DS1302时钟线引脚
  7. sbit T_IO = P1^4;      //DS1302数据线引脚
  8. sbit T_RST = P1^2;     //DS1302复位线引脚
  9. sbit  RS=P1^7;                        //定义LCD的控制线
  10. sbit  RW=P1^6;
  11. sbit  EN=P1^5;
  12. sbit  key0=P3^0;                //定义按键
  13. sbit  key1=P3^1;
  14. sbit  key2=P3^2;
  15. sbit ACC7 =ACC^7;     
  16. sbit ACC0 =ACC^0;
  17. char line1[]="LCD test program";
  18. char line2[]="Everything is OK";
  19. char line3[]="Welcome to you  ";
  20. char line4[]="Welcome to using";
  21. void init_LCD(void);
  22. void write_inst(char);         // 写入指令函数
  23. void write_char(char);         // 写入字元函数
  24. void check_BF(void);         // 检查忙碌函数
  25. void delay1ms(int);
  26. uchar  datechar[]={"DATE:"};
  27. uchar  timechar[]={"TIME:"};
  28. uchar  datebuffer[8]={0,0,0x2d,0,0,0x2d,0,0};      //定义日历显示缓冲区
  29. uchar  timebuffer[8]={0,0,0x3a,0,0,0x3a,0,0};      //定义时间显示缓冲区
  30. uchar data ttime[3]={0x00,0x00,0x00};   //分别为秒、分和小时的值
  31. uchar data tdata[3]={0x00,0x00,0x00};  //分别为年、月、日
  32. //往DS1302写入1Byte数据
  33. void  WriteB(uchar  ucDa)   
  34. {
  35. uchar  i;
  36. ACC = ucDa;
  37. for(i=8; i>0; i--)
  38. {
  39. T_IO = ACC0;        //相当于汇编中的 RRC
  40. T_CLK = 1;
  41. T_CLK = 0;
  42. ACC = ACC >> 1;
  43. }
  44. }
  45. //从DS1302读取1Byte数据
  46. uchar  ReadB(void)                 
  47. {
  48. uchar i;
  49. for(i=8; i>0; i--)
  50. {
  51. ACC = ACC >>1;
  52. ACC7 = T_IO;T_CLK = 1;T_CLK = 0;    //相当于汇编中的 RRC         
  53. }
  54. return(ACC);
  55. }
  56. //DS1302单字节写,向指定单元写命令/数据,ucAddr: DS1302地址, ucDa: 要写的命令/数据
  57. void  v_W1302(uchar ucAddr,uchar ucDa)
  58. {
  59. T_RST = 0;
  60. T_CLK = 0;
  61. _nop_();_nop_();
  62. T_RST = 1;
  63. _nop_();_nop_();
  64. WriteB(ucAddr);           /* 地址,命令 */
  65. WriteB(ucDa);            /* 写1Byte数据*/
  66. T_CLK = 1;
  67. T_RST =0;
  68. }
  69. //DS1302单字节读,从指定地址单元读出的数据
  70. uchar  uc_R1302(uchar  ucAddr)
  71. {
  72. uchar ucDa=0;
  73. T_RST = 0;T_CLK = 0;

  74. T_RST = 1;
  75. WriteB(ucAddr);            /*写地址*/
  76. ucDa = ReadB();           /*读1Byte命令/数据 */

  77. T_CLK = 1;T_RST =0;
  78. return(ucDa);
  79. }
  80. //LCD检查忙函数
  81. void  fbusy()
  82. {

  83.         P2 = 0xff;
  84.         RS = 0;
  85.         RW = 1;
  86.         EN = 1;
  87.         EN = 0;
  88.         while((P2 & 0x80))
  89.         {
  90.         EN = 0;        
  91.         EN = 1;               
  92.         }
  93. }
  94. //LCD写命令函数
  95. void  wc51r(uchar  j)
  96. {
  97.     fbusy();
  98.         EN = 0;
  99.         RS = 0;
  100.         RW = 0;
  101.         EN = 1;
  102.         P2 = j;
  103.         EN = 0;
  104. }
  105. //LCD写数据函数
  106. void  wc51ddr(uchar  j)
  107. {
  108.          fbusy();                //读状态;
  109.         EN = 0;
  110.         RS = 1;
  111.         RW = 0;
  112.         EN = 1;
  113.         P2 = j;
  114.         EN = 0;
  115. }
  116. void  init()                //LCD1602初始化
  117. {
  118. while(1)
  119. {                                                                //指定第一行位置
  120.   write_inst(0x80);
  121.   for(j=0;j<16;j++)
  122.    write_char(line1[j]);                //循环显示16个字符
  123.   write_inst(0xc0);                                //指定第二行位置
  124.   for(j=0;j<16;j++)
  125.    write_char(line2[j]);                //循环显示16个字符
  126.   delay1ms(2000);                //延时2s  (STC89C51:2000)(MPC82G516:20000)               
  127.   write_inst(0x80);
  128.   for(j=0;j<16;j++)
  129.    write_char(line3[j]);
  130.   write_inst(0xc0);
  131.   for(j=0;j<16;j++)
  132.    write_char(line4[j]);
  133.   delay1ms(2000);
  134. }
  135. }

  136. void init_LCD(void)
  137. {
  138. write_inst(0x38);                                   //指令6:设定两行
  139. //write_inst(0x08);                                //指令4:关闭显示
  140. wc51r(0x01);         //清屏
  141. wc51r(0x38);         //使用8位数据,显示两行,使用5*7的字型
  142. wc51r(0x0c);         //显示器开,光标开,字符不闪烁
  143. wc51r(0x06);         //字符不动,光标自动右移一格
  144. }
  145. //************延时函数************
  146. void  delay(uint  i)        //延时函数
  147. {uint  y,j;
  148. for  (j=0;j<i;j++){
  149. for (y=0;y<0xff;y++){;}}
  150. }
  151. void  main(void)
  152. {
  153. uchar  i,set;
  154. uchar data temp;


  155. SP=0X50;
  156. delay(10);
  157. init();
  158. wc51r(0x80);
  159.          
  160. for (i=0;i<5;i++) wc51ddr(datechar[i]);   //第一行开始显示DATA:     
  161. wc51r(0xc0);           
  162. for (i=0;i<5;i++) wc51ddr(timechar[i]);   //第二行开始显示TIME:     
  163. while(1)
  164.         {P3=0XFF;
  165.                 if(key0==0) { delay(10);if (key0==0) { while (key0==0); set++; if
  166. (set==6) set=0;}}
  167.         if(key1==0) { delay(10);    //如果是加1键,则日历、时钟相应位加1
  168.                 if (key1==0) { while (key1==0);
  169.                                  switch(set)
  170.                                   {  
  171.                              case 1:        tdata[0]++;if (tdata[0]==100) tdata[0]=0;
  172.                                 temp=(tdata[0]/10)*16+tdata[0]%10;
  173.                        v_W1302(0x8e,0);
  174.                                 v_W1302(0x8c,temp);
  175.                            v_W1302(0x8e,0x80);
  176.                                   break;         
  177.                                 case 2:        tdata[1]++;if (tdata[1]==13) tdata[1]=1;
  178.                                 temp=(tdata[1]/10)*16+tdata[1]%10;
  179.                        v_W1302(0x8e,0);
  180.                                 v_W1302(0x88,temp);
  181.                            v_W1302(0x8e,0x80);
  182.                                   break;        
  183.                                 case 3:        tdata[2]++;if (tdata[2]==32) tdata[2]=1;
  184.                                 temp=(tdata[2]/10)*16+tdata[2]%10;
  185.                        v_W1302(0x8e,0);
  186.                                 v_W1302(0x86,temp);
  187.                            v_W1302(0x8e,0x80);
  188.                                   break;
  189.                                 case 4:        ttime[2]++;if (ttime[2]==24) ttime[2]=0;
  190.                                 temp=(ttime[2]/10)*16+ttime[2]%10;
  191.                        v_W1302(0x8e,0);
  192.                                 v_W1302(0x84,temp);
  193.                            v_W1302(0x8e,0x80);
  194.                                   break;
  195.                             case 5:        ttime[1]++;if (ttime[1]==60) ttime[1]=0;
  196.                                 temp=(ttime[1]/10)*16+ttime[1]%10;
  197.                        v_W1302(0x8e,0);
  198.                                 v_W1302(0x82,temp);
  199.                            v_W1302(0x8e,0x80);
  200.                                   break;
  201.                                 }
  202.                         }
  203.                 }
  204.         if(key2==0) { delay(10);     //如果是减1键,则日历、时钟相应位减1
  205.               if (key2==0) { while (key2==0);
  206.                             switch(set)
  207.                                 {  
  208.                                    case 1:        tdata[0]--;if (tdata[0]==0xff) tdata[0]=99;
  209.                                 temp=(tdata[0]/10)*16+tdata[0]%10;
  210.                     v_W1302(0x8e,0);
  211.                                 v_W1302(0x8c,temp);
  212.                     v_W1302(0x8e,0x80);
  213.                                 break;         
  214.                                 case 2:        tdata[1]--;if (tdata[1]==0x00) tdata[1]=12;
  215.                                 temp=(tdata[1]/10)*16+tdata[1]%10;
  216.                     v_W1302(0x8e,0);
  217.                                 v_W1302(0x88,temp);
  218.                         v_W1302(0x8e,0x80);
  219.                                 break;        
  220.                                 case 3:        tdata[2]--;if (tdata[2]==0x00) tdata[2]=31;
  221.                                 temp=(tdata[2]/10)*16+tdata[2]%10;
  222.                         v_W1302(0x8e,0);
  223.                                 v_W1302(0x86,temp);
  224.                         v_W1302(0x8e,0x80);
  225.                                 break;
  226.                                 case 4:        ttime[2]--;if (ttime[2]==0xff) ttime[2]=23;
  227.                                 temp=(ttime[2]/10)*16+ttime[2]%10;
  228.                     v_W1302(0x8e,0);
  229.                                 v_W1302(0x84,temp);
  230.                     v_W1302(0x8e,0x80);
  231.                                 break;
  232.                                 case 5:        ttime[1]--;if (ttime[1]==0xff) ttime[1]=59;
  233.                                 temp=(ttime[1]/10)*16+ttime[1]%10;
  234.                     v_W1302(0x8e,0);
  235.                                 v_W1302(0x82,temp);
  236.                     v_W1302(0x8e,0x80);
  237. ……………………

  238. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
109 115 121 205 210 电子时钟设计.zip (254.24 KB, 下载次数: 56)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:505337 发表于 2019-4-23 12:02 来自手机 | 只看该作者
没有闹钟功能呀,按键不能用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表