找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 17124|回复: 15
收起左侧

单片机电子时钟设计-DS1302 1602 可调闹钟

  [复制链接]
ID:467200 发表于 2019-1-12 23:01 | 显示全部楼层 |阅读模式
摘要
随着单片机技术的飞速发展,在其推动下,现代的电子产品几乎渗透到了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高。
时间就是金钱、时间就是生命、时间就是胜利……,准确的掌握时间和分配时间对人们来说至关重要,时钟是我们生活中必不可少的工具。电子钟的设计方法有很多种,但是基于单片机并通过LCD显示的电子时钟具有编程灵活、精确度高、便于携带、显示直观等特点。
    利用STC89C52单片机对DS1302时钟芯片进行读写操作并通过1602字符液晶显示实时时钟信息,这样便构成了一个单片机电子时钟。

目录

绪论
概述
研究目的
第1章 设计要求与方案论证
1.1 设计要求
1.2 系统基本方案选择和论证
1.2.1 单片机芯片的选择方案和论证
1.2.2 显示模块选择方案和论证
1.2.3 时钟芯片的选择方案和论证2
1.3 电路设计最终方案决定
第2章 主要元件介绍3
2.1  STC89C52以及最小系统介绍3
2.1.1  STC89C52主要功能及PDIP封装
2.1.2  STC89C52引脚介绍
2.1.3  STC89C52最小系统4
2.2  DS1302时钟芯片以及集成时钟模块介绍5
2.2.1  DS1302概述6
2.2.2  DS1302引脚介绍6
2.2.3  DS1302使用方法6
        2.2.4  时钟集成模块内部原理图以及实物图8
2.3 1602字符液晶以及显示模块介绍
2.3.1 1602液晶概述
2.3.2 1602引脚介绍
2.3.3 1602字符液晶使用方法
2.3.4 LCD显示模块原理图13
第3章 系统硬件设计
3.1 电路设计框图
3.2 系统硬件概述
第4章 系统的软件设计
4.1 程序流程框图
第5章 系统测试与总结
5.1 系统测试17
5.2 总结17
致谢18
参考文献18
源程序清单18
附录35

概述
时间,对人们来说是非常宝贵的,准确的掌握时间和分配时间对人们来说至关重要。因此自从时钟发明的那刻起,就成为人类的好朋友。随着时间的流逝,科学技术的不断发展和提高,人们对时间计量的精度要求越来越高,应用越来越广。怎样让时钟更好、更方便、更精确的显示时间,这就要求人们不断设计研发出新型的时钟。
高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟,石英表,石英钟都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调校。数字式电子钟用集成电路计时时,译码代替机械式传动,用LED显示器代替指针进而显示时间,减小了计时误差,这种表具有时,分,秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好。
时钟电路在计算机系统中起着非常重要的作用,是保证系统正常工作的基础。在单片机的应用系统中,时钟有两个方面的含义:一是指为保障系统正常工作的基准振荡定时信号,主要由晶振和外围电路组成,晶振频率的大小决定了单片机系统工作的快慢;二是指系统的标准定时时钟,即定时时间,它通常有两种实现方法:一是用软件实现,即用单片机内部的可编程定时器/计数器来实现;二是用专门的时钟芯片实现。
研究目的
通过利用STC89C52单片机和DS1302芯片以及外围的按键和LCD显示器等部件,设计一个基于单片机的电子时钟。设计的电子时钟通过液晶显示器显示,并能通过按键对时间以及闹钟进行设置。
   第1章 设计要求与方案论证
1
.1 设计要求
  • 具有年、月、日、星期、时、分、秒显示功能()
  • 具备年、月、日、星期、时、分、秒校准功能
  • 具有闹钟显示、调节设定、鸣叫功能

1.2 系统基本方案选择和论证
1
.2.1 单片机芯片的选择方案和论证:
方案一:
采用STC89C52芯片作为硬件核心。STC89C52内部具有8KB ROM 存储空间,512字节数据存储空间,带有2K字节的EEPROM存储空间,与MCS-51系列单片机完全兼容,STC89C52可以通过串口下载。
方案二:
   采用AT89S52。AT89S52片内具有8K字节程序存储空间,256字节的数据存储空间没有EEPROM存储空间,也与MCS-51系列单片机完全兼容,具有在线编程可擦除技术。
              两种单片机都完全能够满足设计需要,STC89C52相对ATS89C52价格便宜,且抗干扰能力强。考虑到成本因素,因此选用STC89C52。

1.2.2 显示模块选择方案和论证:
方案一:
     采用点阵式数码管显示。点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用在显示数字显得太浪费,且也相对较高,所以不用此种作为显示。
方案二:
采用LED数码管动态扫描。LED数码管价格便宜,对于显示数字最合适,但功耗较大,且显示容量不够,所以也不用此种方案。
方案三:
   采用LCD液晶显示屏。液晶显示屏的显示功能强大,可显示大量文字,显示多样,清晰可见,且价格适中,所以采用了LCD数码管作为显示。

1.2.3 时钟芯片的选择方案和论证:
方案一:
   直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、星期、时、分、秒计数。采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。所以不采用此方案。
方案二:
  采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动对秒、分、时、日、周、月、年以及闰年补偿的年进行计数,而且精度高,工作电压2.5V~5.5V范围内,2.5V时耗电小于300nA.

1.3 电路设计最终方案决定
综上各方案所述,对此次作品的方案选定: 采用STC89C52单片机作为主控制系统;采用DS1302作为时钟芯片;采用1602 LCD液晶作为显示器件。

2.2  DS1302时钟芯片以及时钟集成模块介绍
2.2.1  DS1302概述
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟芯片,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用双电源供电(主电源和备用电源),同时提供了对后背电源进行涓细电流充电的能力。采用三线接口与CPU进行同步通信
图4:DS1302封装图

2.2.2  DS1302引脚介绍
各引脚功能为:
Vcc:    主电源;Vcc2:备用电源。当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电;当Vcc2<Vcc1时,由Vcc1向DS1302供电。
SCLK:串行时钟输入端,控制数据的输入与输出
I/O:   三线接口时的双向数据线
CE:   输入信号,在读、写数据期间必须为高

2.2.3  DS1302使用方法
(1) 时钟芯片DS1302的工作原理:
     DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置 “0”,接着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如图5所示。表2为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。位1至位5指操作单元的地址。位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。控制字节总是从最低位开始输入/输出的。表6为DS1302的日历、时间寄存器内容:“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。“WP”
是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。当“WP”为1时,写保护位防止对任一寄存器的写操作。
(2) DS1302的控制字节
DS1302的控制字如表所示。控制字节最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始传输
1
RAM
A4
A3
A2
A1
A0
RD
CK
WR

表2:DS1302控制字
(3) 数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。其读写时序如图示
图5:DS1302读写时序
(4)DS1302寄存器
DS1302中与时间、日期有关的寄存器共有12个,其中7个存放数据的格式为BCD码格式,其读写地址如下表所示
读寄存器
写寄存器
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
Bit7
范围
81H
80H
CH
10秒
00--59
83H
82H

10分
00--59
85H
84H
12
0
10
0--23
24
AM/PM
1--12
87H
86H


10日
1--31
89H
88H



10月
1--12
8BH
8AH
0
0
0
0
0
1--7
8DH
8CH
10年
00--99
8FH
8EH
WP
0
0
0
0
0
0
0
――
表3:DS1302时钟寄存器
第一行秒寄存器,CH为时钟暂停标志位,该位为1时时钟停止,该位为0时时钟运行
第二行分寄存器,bit0~bit6表示分钟数,因采用BCD编码,所以低四位最大能表示的数字为9,计数满向高三位进1。
第三行时寄存器,12/24用来定义DS1302小时的运行模式,12小时模式下bit5为1表示PM下午,bit5为0表示AM上午
第八行控制寄存器,bit7是写保护位WP,当WP为1时,写保护位可防止对任一寄存器的写操作,在任何的对时钟和RAM的写操作之前,WP位必须为0
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
2.2.4  时钟集成模块内部原理图以及实物图
       图6:DS1302内部原理图
图7:DS1302实物图

2. 3  1602字符液晶以及显示模块介绍2.3.1  1602液晶概述
工业字符型液晶,1602是指显示的内容为16*2,即能够同时显示两行,每行16个字符。常见的1602字符液晶有两种,一种显示的是绿色背光黑色字体,另一种显示蓝色背光白色字体,目前市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的。本课题所用1602液晶模块,显示屏是蓝色背光白色字体。如图6所示
图8:1602字符液晶
2.3.2 1602引脚介绍
编号
符号
引脚说明
编号
符号
引脚说明
1
GND
电源地
2
VCC
电源正极
3
VO
液晶显示对比度调节端
4
RS
数据/命令选择端
5
R/W
读写选择
6
E
使能信号
7
D0
数据口
8
D1
数据口
9
D2
数据口
10
D3
数据口
11
D4
数据口
12
D5
数据口
13
D6
数据口
14
D7
数据口
15
BLA
背光电源正
16
BLK
背光电源负
表4:1602字符液晶引脚说明
各个引脚具体功能说明:
第1脚:GND为地电源。
第2脚:VCC接5V正电源。
第3脚:VO为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生重影,使用一个1K的电位器调整对比度。
第4脚:RS为寄存器选择,高电平时选择数据寄存器,低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:DB0~DB7为8位双向数据线。
第15~16脚:背光灯电源。
2.3.3  1602字符液晶使用方法
(1)基本操作时序
操作
输入
输出
读状态
RS=L,RW=H,E=H
D0~D7=状态字
写指令
RS=L,RW=L,D0~D7=指令码,E=高脉冲
读数据
RS=H,RW=H,E=H
D0~D7=数据
写数据
RS=H,RW=L,D0~D7=数据,E=高脉冲
图9:1602液晶读时序图
图10:1602液晶写时序图
(2)RAM            
1602液晶控制器芯片内部带有80个8位的RAM缓冲区,其地址和屏幕的对应关系如图7示
图11
(3)1602字符液晶字库
     1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如下表所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”

2.3.4 LCD显示模块原理图

图13 LCD显示模块原理图


第3章 系统硬件设计
3.1 电路设计框图
图14:硬件框图
3.2 系统硬件概述
电路以STC89C52单片机最小系统为控制核心,时钟电路由高精度低功耗的DS1302提供,采用三线接口与CPU进行同步通信,输入部分采用四个独立式按键S1、S2、S3、S4。1602液晶显示部分,D0-D7口与单片机P0口相连。具体电路连接,详见附录1

4章 系统的软件设计
4.1程序流程框图
图15:主程序框图

图16:按键程序图
第五章 系统测试与总结
5.1 系统测试

从开始准备到写完论文大概花了一周时间,原理图和PCB制作花了一天时间,在这期间主要遇到的问题是Altium Designer软件的使用,遇到问题主要到百度上查找答案,PCB做出之后紧接着就是焊接元器件,这部分由于粗心将电解电容正负极焊反,后面经过万用表不断的测试才判断出来,及时纠正过来,焊接与硬件调试大概花了半天时间。紧接着大部分的时间都花费在硬件与软件的结合调试上,在调试过程中使用自己在网上买的51单片机开发板上进行一步一步的调试。由于是第一次做课程设计,同时也是第一次写这么综合的程序,所以在调试过程中遇到很多问题,一部分是关于DS1302与1602的硬件特点以及在硬件的基础之上驱动程序的调用,这里主要是网上找资料去学会调用与编写,主要是通过网上视频教学 ;另一部分是自己做的硬件存在很多误差,特别是电源供电部分,刚开始是用废弃的鼠标上的那个USB接口线插在电脑上供电,但由于电源介入硬件的是两个排针,所以很不稳定,1602上总乱码,或者5个按键随便一个按下都是复位,而且从电脑输出5V接到硬件系统后只有4.5V了,想了一下,最后拿出上学期期末自己做的电源将它调节到6V后,接入硬件系统就能达到5V。


5.2 总结

通过本次论文设计,使我加深了对单片机的认识,并且熟悉了单片机系统的设计流程,收获丰硕。功能上基本达标:时钟与闹钟的显示,调时间和闹钟功能以及闹钟鸣叫功能。时钟与闹钟显示功能,精确度完全可以满足日常生活显示时间的需要;调时间与闹钟功能,方便快捷。硬件设施基本合乎要求,软件设计可以配合硬件实现其功能。
技术在不断进步,机械式时钟已经被淘汰,取而代之的是具有高度准确性和直观性且无机械装置,具有更长的使用寿命等优点的电子时钟。电子时钟更具人性化,更能提高人们的生活质量,更受人们欢迎。机械时代已经远去,电子时代已经到来。做为新时代的我们,更应该提高自身能力,适应新时代的发展。知识来自实践,多从生活中探寻所需要的。
从这次的论文设计中,我真正的体会到,知识的重要性,特别是要理论联系实际,把我们所学的理论知识运用到实际生活当中,要用知识改变一切。

附录一:



                      系统原理图



附录二:


                         PCB


附录三:
首先上电进入欢迎界面,如上图所示,显示5S钟。
上电后的整体外观图,各按键的功能都有标注
按K1进入调时状态按得次数不同光标显示的位置不同,从而进行年、月、日、时、分、秒、的调整,按8次时退出,按K2调时,K3确定键,确认所调时间。
按K4进入闹铃调整状态,按一次光标显示在闹铃秒位置,从而进行秒的调整,当按二次光标显示在闹铃时位置,从而进行时的调整,按第三次退出调整状态。

单片机源程序如下:
  1. #include<reg52.h>//52单片机头文件,规定了52单片机的寄存器和IO口等
  2. #include<intrins.h>//_nop_空指令及左右循环移位子函数库
  3. #define uchar unsigned char//宏定义
  4. #define uint unsigned int//宏定义
  5. sbit lcden=P2^7;//定义下面通过lcden来操作P2^7口,1602液晶使能控制端
  6. sbit lcdwr=P2^5;//定义下面通过lcdrw来操作P2^5口,1602读写选择端
  7. sbit lcdrs=P2^6;//定义选数据寄存器选指令寄存器控制端
  8. sbit sda=P3^4;//定义DS1302数据总线
  9. sbit rst=P3^5;//DS1320复位
  10. sbit sck=P3^6;//定义时钟总线
  11. sbit s1=P1^0;//定义设置按钮
  12. sbit s2=P1^1;//定义调时按钮
  13. sbit s3=P1^2;//定义确定按钮
  14. sbit s4=P1^3;
  15. sbit ACC0=ACC^0;
  16. sbit ACC7=ACC^7;
  17. sbit BELL=P1^5;
  18. char fen,shi,miao,ri,yue,nian,zhou,s1num,s2num,s4num,flag1,flag2,lshi,lfen;
  19. uchar code table[]={" 2012-  -       "};//要写入1602液晶的数据
  20. uchar code table1[]={"   :  :     :   "};//字库中的字可直接以外加""号的形式直接写入
  21. uchar code table2[]={" Welcome To Lcd!"};//欢迎界面
  22. uchar code table3[]={"Happy Every Day!"};                 //欢迎界面
  23. /*******************************************************************************
  24. 时函数,z的取值为这个函数的延时ms数,delay(200);大约延时200ms. delay(500);大约延时500ms
  25. *******************************************************************************/
  26. void delay(uint z)
  27. {                                                                                    
  28.               uint x,y;
  29.               for(x=z;x>0;x--)
  30.               for(y=110;y>0;y--);
  31. }
  32. /*********************蜂鸣器函数************************************************/
  33. void didi()
  34. {               
  35.     uchar i;
  36.      for(i=0;i<60;i++)
  37.       {
  38.         BELL = 0;
  39.                             delay(1);
  40.                    BELL = 1;
  41.                             delay(1);
  42.        }
  43. }

  44. /*******************向1602液晶中写一个指令**************************************/
  45. void write_com(uchar com)
  46. {            
  47.               lcdwr=0;                                          //lcdwr为读写控制端,lcdwr=0,这里可不写
  48.               lcdrs=0;           //液晶rs接口为0时,写指令,rs为1时写数据
  49.               P0=com;          //将要写的指令赋给P0口,
  50.               delay(5);    //由1602读写操作时序图,先将指令赋给P0口,延时后将使能
  51.               lcden=1;    //  端lcden置高,再延时一段时间,然后将lcden置低,这样指令
  52.               delay(5);                // 就写入到LCD了            
  53.               lcden=0;
  54. }
  55. /****************************向液晶写数据***************************************/
  56. void write_data(uchar date)//与写指令类似,这里lcdrs设为1
  57. {
  58.               lcdrs=1;
  59.               P0=date;
  60.               delay(5);
  61.               lcden=1;
  62.               delay(5);
  63.               lcden=0;
  64. }
  65. /*****************************初使化1602液晶************************************/
  66. void init_1602()
  67. {

  68.               lcdwr=0;
  69.               lcden=0;
  70.               write_com(0x38);//设置LCD为16*2显示、5*7点阵、8位数据接口模式
  71.               write_com(0x0c);//开显示、不显示光标
  72.               write_com(0x06);//写一个字符后,地址指针加1
  73.               write_com(0x01);//显示清0
  74. }
  75. /*******************************************************************************/
  76. void gudingtime_1602()
  77. {
  78.     uchar num;
  79.               write_com(0x80);//将指针指向初始位置
  80.               for(num=0;num<16;num++)//循环函数,用于将" 2012-  -     "写入液晶
  81.                                           write_data(table[num]);
  82.               write_com(0x80+0x40);//将指针指向1602液晶的第二行
  83.               for(num=0;num<16;num++)//功能与上同,用于将"   :  :     :   "写入
  84.                                           write_data(table1[num]);
  85. }
  86. /**************************显示欢迎界面函数*************************************/
  87. void displaystar(void)
  88. {
  89.               uchar i;
  90.               write_com(0x80);
  91.               for(i=0;i<16;i++)
  92.               write_data(table2[i]);
  93.               write_com(0x80+0x40);
  94.               for(i=0;i<16;i++)
  95.               write_data(table3[i]);
  96. }
  97. /***************************显示时间、日期子函数*********************************/
  98. void write_sfm(uchar add,uchar time)//用于在1602上显示年、月、日、时、分、秒。Add为显示位置,time为要显示的内容
  99. {                             
  100.               uchar shiwei,gewei;                                                                                   
  101.               shiwei=time/16;   //将从DS1302中读取的BCD码数据转化成10进制个位和10
  102.               gewei=time%16;   //进制十位
  103.               write_com(add+0x80);//定义显示在液晶的什么位置
  104.               write_data(0x30+shiwei);//由1602液晶字库可知,0~9的数据码分别对应0x30~0x39
  105.               write_data(0x30+gewei);              //初使化中设定了写一个字符后,地址指针加1,因此这里
  106. }                     // 不用重新光标写位
  107. /**************************显示周子函数*****************************************/
  108. void write_zhou(uchar time1)//用于在1602上显示周信息,与显示
  109. {                        //时间日期子函数类似
  110.               uchar gewei;
  111.               gewei=time1%16;//一周七天,因此只需个位
  112.               write_com(0x80+13);
  113.               write_data(0x30+gewei);
  114. }
  115. /***************************写数据字节子函数************************************/
  116. void Input_1byte(uchar TD)//写一字节数据
  117. {
  118.     uchar i;
  119.     ACC=TD;
  120.     for(i=8;i>0;i--)
  121.     {
  122.        sda=ACC0;
  123.        sck=1;
  124.        sck=0;
  125.        ACC=ACC>>1;
  126.     }
  127. }


  128. /*************************读数据字节子函数**************************************/
  129. uchar Output_1byte(void)//读一字节数据
  130. {
  131.     uchar i;
  132.     for(i=8;i>0;i--)
  133.      {
  134.          ACC=ACC>>1;
  135.          ACC7=sda;
  136.          sck=1;
  137.          sck=0;
  138.      }

  139.      return(ACC);

  140. }
  141. /***************************写DS1302数据函数***********************************/
  142. void write_1302(uchar DS_ADD,uchar DS_DAT)//写操作
  143. {  
  144.                             rst=0;
  145.                             sck=0;
  146.                             rst=1;
  147.                             Input_1byte(DS_ADD);
  148.                             Input_1byte(DS_DAT);
  149.                             sck=1;
  150.                             rst=0;
  151. }

  152. /***************************读DS1302数据函数***********************************/
  153. uchar read_1302(uchar DS_ADD)//读操作
  154. {  
  155.                 uchar DS_INF;
  156.                 rst=0;
  157.                 sck=0;
  158.                 rst=1;
  159.                 Input_1byte(DS_ADD);
  160.                 DS_INF=Output_1byte();
  161.                 sck=1;
  162.                 rst=0;
  163.                 return(DS_INF);
  164. }

  165. /*************************初始化DS1302子函数***********************************/
  166. void inital_1302()
  167. {
  168.     write_1302(0x8e,0x00);//禁止写保护
  169.     write_1302(0x90,0xaa);//定义充电
  170.               write_1302(0x80,0x53);//秒  
  171.     write_1302(0x84,0x13);//时   
  172.               write_1302(0x82,0x43);//分
  173.               write_1302(0x8c,0x12);//年
  174.               write_1302(0x88,0x06);//月
  175.               write_1302(0x86,0x03);//日
  176.               write_1302(0x8a,0x06);//星期
  177.     write_1302(0xc0,0x08);//闹钟小时初始化
  178.               write_1302(0xfc,0x00);//闹钟分钟初始化
  179.               write_1302(0x8e,0x80);//开保护

  180. }
  181. /********************************************************************************
  182.                               扫描函数
  183. ********************************************************************************/

  184. void keyscan()
  185. {
  186.               if(s1==0&&s4num==0)              //按键1按下且s4再次之前未曾按过
  187.               {
  188.                             delay(5);
  189.                             if(s1==0&&s4num==0)
  190.                             {  
  191. flag1=1;
  192.                                 s1num++;
  193.                                           while(!s1);didi();
  194.                                           if(s1num==1)
  195.                                           {                                                      
  196.                                                         write_com(0x80+0x40+8);//光标移动到**位置
  197.                                                         write_com(0x0f);//显示光标
  198.                                           }

  199.                                           if(s1num==2)
  200.                                           {
  201.                                                            write_1302(0x8e,0x00);//禁止写保护
  202.                                                         write_1302(0x80,miao);//写入秒信息
  203.                                                         write_1302(0x8e,0x80);//开写保护
  204.                                                         write_com(0x80+0x40+5);
  205.                                           }
  206.                                           if(s1num==3)
  207.                                           {
  208.                                                            write_1302(0x8e,0x00);
  209.                                                         write_1302(0x82,fen);
  210.                                                         write_1302(0x8e,0x80);
  211.                                                         write_com(0x80+0x40+2);                                                                                                               
  212.                                           }
  213.                                           if(s1num==4)
  214.                                           {
  215.                                                         write_1302(0x8e,0x00);
  216.                                                         write_1302(0x88,yue);
  217.                                                         write_1302(0x8e,0x80);
  218.                                               write_com(0x80+13);
  219.                                           }
  220.                                           if(s1num==5)
  221.                                           {
  222.                                                         write_1302(0x8e,0x00);
  223.                                                         write_1302(0x84,shi);
  224.                                                         write_1302(0x8e,0x80);
  225.                                                         write_com(0x80+10);
  226.                                           }
  227.                                           if(s1num==6)
  228.                                           {
  229.                                                         write_1302(0x8e,0x00);
  230.                                                         write_1302(0x86,ri);
  231.                                                         write_1302(0x8e,0x80);
  232.                                                         write_com(0x80+7);
  233.                                           }
  234.                                           if(s1num==7)
  235.                                           {
  236.                                                         write_1302(0x8e,0x00);
  237.                                                         write_1302(0x8c,nian);
  238.                                                         write_1302(0x8e,0x80);
  239.                                                         write_com(0x80+4);
  240.                                           }
  241.             if(s1num==8)
  242.                                           {
  243.                                     flag1=0;
  244.                                                         s1num=0;
  245.                                                         write_1302(0x8e,0x00);
  246.                                                         write_1302(0x8a,zhou);
  247.                                                         write_1302(0x8e,0x80);
  248.                                                         write_com(0x0c);//不显示光标
  249.                                           }
  250.                             }
  251.               }            
  252. /*******************************************************************************/              if(s1num!=0&&s4num==0)//按键1按下*次且s4再次之前未曾按过
  253.                             {
  254.                                           if(s2==0)
  255.                                           {
  256.                                                         delay(5);
  257.                                                         if(s2==0)
  258.                                                         {  
  259.                                                                       while(!s2);didi();
  260.                                                                       if(s1num==1)
  261.                                                                       {
  262.                                                                                     int x1,x2;
  263.                                                                                     x1=miao%16;
  264.                                                                                     x2=miao/16;
  265.                                                                                     x1++;
  266.                                                                                     if(x1==10)
  267.                                                                                     {
  268.                                                                                                   x1=0;
  269.                                                                                                   x2++;
  270.                                                                                                   if(x2>=6)
  271.                                                                                                                 x2=0;
  272.                                                                                     }
  273.                                                                                     miao=x1+x2*16;
  274.                                                                                     write_sfm(7+0x40,miao);//将修改的数送到1602显示
  275.                                                                                     write_com(0x80+0x40+8);//挪回光标
  276.                                                                       }
  277.                                                                       if(s1num==2)
  278.                                                                       {
  279.                                                                                     int x3,x4;
  280.                                                                                     x3=fen%16;
  281.                                                                                     x4=fen/16;
  282.                                                                                     x3++;
  283.                                                                                     if(x3==10)
  284.                                                                                     {
  285.                                                                                                   x3=0;
  286.                                                                                                   x4++;
  287.                                                                                                   if(x4>=6)
  288.                                                                                                                 x4=0;
  289.                                                                                     }
  290.                                                                                     fen=x3+x4*16;
  291.                                                                                     write_sfm(4+0x40,fen);
  292.                                                                                     write_com(0x80+0x40+5);
  293.                                                                       }            
  294.                                                                       if(s1num==3)
  295.                                                                       {
  296.                                                                                     int x5,x6;
  297.                                                                                     x5=shi%16;
  298.                                                                                     x6=shi/16;
  299.                                                                                     x5++;
  300.                                                                                     if(x6>=2&&x5>=4)            
  301.                                                                                     {
  302.                                                                                                   x5=0;
  303.                                                                                                   x6=0;
  304.                                                                                     }
  305.                                                                                     if(x5==10)
  306.                                                                                     {
  307.                                                                                                   x5=0;
  308.                                                                                                   x6++;
  309.                                                                                     }
  310.                                                                                     shi=x5+x6*16;
  311.                                                                                     write_sfm(1+0x40,shi);
  312.                                                                                     write_com(0x80+0x40+2);
  313.                                                                       }
  314.                                                                       if(s1num==4)
  315.                                                                       {
  316.                                                                                     zhou++;
  317.                                                                                     if(zhou==8)
  318.                                                                                     zhou=1;
  319.                                                                                     write_zhou(zhou);
  320.                                                                                     write_com(0x80+13);
  321.                                                                                    
  322.                                                   }
  323.                                                                       if(s1num==5)
  324.                                                                       {
  325.                                                                                     int x5,x6;
  326.                                                                                     x5=ri%16;
  327.                                                                                     x6=ri/16;
  328.                                                                                     x5++;
  329.                                                                                     if(x6>=3&&x5>=1)            
  330.                                                                                     {
  331.                                                                                                   x5=1;
  332.                                                                                                   x6=0;
  333.                                                                                     }
  334.                                                                                     if(x5==10)
  335.                                                                                     {
  336.                                                                                                   x5=0;
  337.                                                                                                   x6++;
  338.                                                                                     }
  339.                                                                                     ri=x5+x6*16;
  340.                                                                                     write_sfm(9,ri);
  341.                                                                                     write_com(0x80+10);
  342.                                                                       }
  343.                                                                       if(s1num==6)
  344.                                                                       {
  345.                                                                                     int x5,x6;
  346.                                                                                     x5=yue%16;
  347.                                                                                     x6=yue/16;
  348.                                                                                     x5++;
  349.                                                                                     if(x6>=1&&x5>=3)            
  350.                                                                                     {
  351.                                                                                                   x5=1;
  352.                                                                                                   x6=0;
  353.                                                                                     }
  354.                                                                                     if(x5==10)
  355.                                                                                     {
  356.                                                                                                   x5=0;
  357.                                                                                                   x6++;
  358.                                                                                     }
  359.                                                                                     yue=x5+x6*16;
  360.                                                                                     write_sfm(6,yue);
  361.                                                                                     write_com(0x80+7);
  362.                                                   }
  363.                                                                       if(s1num==7)
  364.                                                                       {
  365.                                                                                     int x5,x6;
  366.                                                                                     x5=nian%16;
  367.                                                                                     x6=nian/16;
  368.                                                                                     x5++;
  369.                                                                                     if(x6>=2&&x5>=1)            
  370.                                                                                     {
  371.                                                                                                   x5=1;
  372.                                                                                                   x6=0;
  373.                                                                                     }
  374.                                                                                     if(x5==10)
  375.                                                                                     {
  376.                                                                                                   x5=0;
  377.                                                                                                   x6++;
  378.                                                                                     }
  379.                                                                                     nian=x5+x6*16;
  380.                                                                                     write_sfm(3,nian);
  381.                                                                                     write_com(0x80+4);
  382.                                                   }
  383.                                                         }
  384.                                           }
  385.                   }
  386. /*******************************************************************************/

  387.               if(s1num!=0||s4num!=0)// 在调整模式下
  388.                             {
  389.                                           if(s3==0)//如果确定键按下
  390.                                           {
  391.                                                         delay(5);
  392.                                                         if(s3==0) //延时并重新检测S3是否按下,用于差小误差
  393.                                                         {
  394.                                                            if(s1num!=0)
  395.                                                            {
  396.                                                             while(!s3);didi();//在松手时将调整后的时间、日期及周信息写入DS1302,退出调整模式并隐藏光标,按键次数清0
  397.                                                                       write_1302(0x8e,0x00);
  398.                                                                          write_1302(0x80,miao);
  399.                                                             write_1302(0x84,shi);
  400.                                                                       write_1302(0x82,fen);
  401.                                                                       write_1302(0x8a,zhou);
  402.                                                                       write_1302(0x8c,nian);//年
  403.                                                                       write_1302(0x88,yue);//月
  404.                                                                       write_1302(0x86,ri);
  405.                                                                       write_1302(0x8e,0x80);
  406.                                                                       flag1=0;
  407.                                                                       write_com(0x0c);
  408.                                                                       s1num=0;
  409.                    }
  410.                                                            if(s4num!=0)
  411.                                                            {
  412.                                                                          while(!s3);didi();//在松手时将调整后的时间、日期及周信息写入DS1302,退出调整模式并隐藏光标,按键次数清0
  413.                     write_1302(0x8e,0x00);
  414.                                                                write_1302(0xc0,lshi);
  415.                     write_1302(0xfc,lfen);
  416.                                                                       write_1302(0x8e,0x80);
  417.                                                                       flag2=0;
  418.                                                                       s4num=0;
  419.                                                                       write_com(0x0c);
  420.                    }

  421.                                                         }
  422.                                           }            
  423.         }

  424.    if(s4==0&&s1num==0)//按键4按下*次且s1再次之前未曾按过
  425.         {
  426.                                 
  427.               delay(5);
  428.                                               if(s4==0&&s1num==0)
  429.                                             {   
  430.                                         s4num++;
  431.                                                                       flag2=1;
  432.                     while(!s4);didi();
  433.                                                               if(s4num==1)
  434.                                                                       {                                                      
  435.                                                                                                                                           
  436.                                                                                     write_com(0x80+0x40+14);
  437.                                                                                     write_com(0x0f);
  438.                                                                       }
  439.                                                                           
  440.                                                                         if(s4num==2)
  441.                                                                       {
  442.                                                                                        write_1302(0x8e,0x00);//禁止写保护
  443.                                                                           write_1302(0xfc,lfen);//闹钟初始化
  444.                                                                                     write_1302(0x8e,0x80);//开写保护
  445.                                                                                     write_com(0x80+0x40+11);
  446.                                                                       }
  447.                                                                       if(s4num==3)
  448.                                                                       {  
  449.                                                                           s4num=0;
  450.                                                                                     flag2=0;
  451.                                                                                        write_1302(0x8e,0x00);//禁止写保护
  452.                                                                                     write_1302(0xc0,lshi);//闹钟初始化
  453.                                                                                     write_1302(0x8e,0x80);//开写保护
  454.                                                                                     write_com(0x0c);//不显示光标
  455.                                                                       }
  456.                                             }
  457.                             }
  458.             
  459.                                           if(s4num!=0&&s1num==0)
  460.                                           {
  461.                                                         if(s2==0)
  462.                                                         {
  463.                                                                       delay(5);
  464.                                                                       if(s2==0)
  465.                                                                       {  
  466.                                                                                     while(!s2);didi();
  467.                                                                                     if(s4num==1)
  468.                                                                                     {
  469.                                                                                                   int x1,x2;
  470.                                                                                                   x1=lfen%16;
  471.                                                                                                   x2=lfen/16;
  472.                                                                                                   x1++;
  473.                                                                                                   if(x1==10)
  474.                                                                                                   {
  475.                                                                                                                 x1=0;
  476.                                                                                                                 x2++;
  477.                                                                                                                 if(x2>=6)
  478.                                                                                                                               x2=0;
  479.                                                                                                   }
  480.                                                                                                   lfen=x1+x2*16;
  481.                                                                                                   write_sfm(13+0x40,lfen);
  482.                                                                                                   write_com(0x80+0x40+14);
  483.                                   }
  484.                                                                                     if(s4num==2)
  485.                                                                                     {
  486.                                                                                                   int x5,x6;
  487.                                                                                                   x5=lshi%16;
  488.                                                                                                   x6=lshi/16;
  489.                                                                                                   x5++;
  490.                                                                                                   if(x6>=2&&x5>=4)            
  491. ……………………

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

以上全部Word格式文档51hei提供下载:
电子时钟设计-DS1302 1602 可调闹钟.doc (3.36 MB, 下载次数: 563)
回复

使用道具 举报

ID:21545 发表于 2019-2-7 21:24 | 显示全部楼层
谢谢介绍的很详细了,适合初学者!!!
回复

使用道具 举报

ID:504761 发表于 2019-4-5 20:34 | 显示全部楼层
这个最后出现乱码是不是程序的问题?我的供电5V没有问题啊,用万用表测了,所以有人能告诉我这个程序哪儿有问题吗?
回复

使用道具 举报

ID:523687 发表于 2019-4-28 20:14 | 显示全部楼层
我下载的里头怎么没有程序 只有设计报告啊。。。
回复

使用道具 举报

ID:505337 发表于 2019-5-4 21:37 来自手机 | 显示全部楼层
只有word
回复

使用道具 举报

ID:591254 发表于 2019-7-27 14:32 | 显示全部楼层
系统原理图怎么没有DS1302的晶振呀求解
回复

使用道具 举报

ID:597910 发表于 2019-8-15 19:16 | 显示全部楼层
为什么LCD1602没显示
回复

使用道具 举报

ID:597910 发表于 2019-8-15 19:19 | 显示全部楼层
LCD没显示和按键不管用,只有1302管用是代码的问题吗
回复

使用道具 举报

ID:285380 发表于 2019-9-27 10:52 | 显示全部楼层
高手啊 ,辛苦了,内容很详细  。
回复

使用道具 举报

ID:606251 发表于 2019-9-27 11:24 | 显示全部楼层
谢谢楼主分享,学习了!
回复

使用道具 举报

ID:436945 发表于 2019-12-24 12:36 | 显示全部楼层
高手 确实是高手
回复

使用道具 举报

ID:858511 发表于 2020-12-11 09:37 | 显示全部楼层
哇,超详细的喔,要是有Proteus仿真就好了
回复

使用道具 举报

ID:858511 发表于 2020-12-11 09:39 | 显示全部楼层
要是加上仿真就好了
回复

使用道具 举报

ID:895836 发表于 2021-4-26 23:12 | 显示全部楼层
只有一个文档
回复

使用道具 举报

ID:186161 发表于 2021-5-1 00:32 | 显示全部楼层
很好,怎么没给加分
回复

使用道具 举报

ID:1080083 发表于 2023-5-30 10:27 | 显示全部楼层
怎么烧录不了?有解决办法吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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