基于51单片机+DS1302时钟模块+LCD1602显示

发布者:二进制心灵最新更新时间:2022-09-20 来源: csdn关键字:51单片机  DS1302  时钟模块  LCD1602显示 手机看文章 扫描二维码
随时随地手机看文章

DS1302时钟模块相关介绍

基本介绍

概述

DS1302 可慢速充电实时时钟芯片包含实时时钟/日历和 31 字节的非易失性静态 RAM。它经过一个简

单的串行接口与微处理器通信。实时时钟/日历可对秒,分,时,日,周,月,和年进行计数,对于小于

31 天的月,月末的日期自动进行调整,还具有闰年校正的功能。时钟可以采用 24 小时格式或带 AM(上

午)/PM(下午)的 12 小时格式。31 字节的== RAM== 可以用来临时保存一些重要数据。使用同步串行通信

简化了 DS1302 与微处理器的通信。与时钟/RAM 通信仅需3 根线:(1)RST(复位),(2)I/O(数据线)

和(3)SCLK(串行时钟)。数据可以以每次一个字节的单字节形式或多达 31 字节的多字节形式传输。DS1302

能在非常低的功耗下工作,消耗小于 1µW 的功率便能保存数据和时钟信息。


特点


在这里插入图片描述

各引脚功能

在这里插入图片描述

各引脚的功能:

Vcc1:主电源;Vcc2:备份电源。 当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2SCLK: 串行时钟,输入,控制数据的输入与输出;

I/O: 三线接口时的双向数据线;

CE: 输入信号,在读和写的器件必须为高。该引脚有两个功能:1.开始控制字访问移位寄存器的控制逻辑;2.提供结束单字节或多字节数据传输的方法。


相关寄存器

有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81H——8DH,写时80H——8CH==)存放的数据格式是BCD码形式。如图所示

在这里插入图片描述

小时寄存器

位7用于定义DS1302是采用12小时模式还是24小时模式。高:12小时模式。在12小时模式时,位5 为1时,表示PM。在24小时模式时,为5是第二个10小时位。

秒寄存器

的就位7定义为时钟暂停标志(CH)。1:时钟振荡器停止,DS1302进入低功耗状态,当该位置为0时,时钟开始运行。

控制寄存器

的位7是写保护位(WP),其他7位均置0,对时钟和RAM进行写操作时,WP必须为0,也就是关闭写保护,当WP为1时,就是只读模式。

DS1302相关的RAM地址

DS1302中附加31字节静态RAM的地址如下图

在这里插入图片描述

DS1302的工作模式寄存器

所谓的突发模式(BURST模式)就是一次性传送多个字节的时钟信号和RAM数据。比如我可以一次性把时间和日期写入,也可以一次性的读出时间和日期。

在这里插入图片描述

通过对 31(十进制)位地址寻址(地址/命令位于 1 至 5=逻辑 1),可以把时钟/日历或 RAM 寄存器规定为多字节方式。如前所述,位 6 规定时钟或 RAM 而位 0 规定读或写。在时钟日历寄存器中的地址 9 至 31或 RAM 寄存器中的地址 31 不能存储数据。在多字节方式中读或写从地址 0 的位 0 开始。当以多字节方式写时钟寄存器时,必须按数据传送的次序写最先 8 个寄存器。意思就是写我们不是只有7个吗?时分秒、年月日、周一共七个 但是吧它得字节数为8 所有要写够8次。

但是,当以多字节方式写 RAM 时,为了传送数据不必写所有 31 个字节。不管是否写了全部 31 个字节,所写的每一个字节都将传送至 RAM。


在这里插入图片描述

DS1302充电寄存器

这个我没整过,全部复制手册的。哈哈


这个寄存器控制 DS1302 的慢速充电特性。图 4 的简化电路表示慢速充电器的基本组成。慢速充电选择(TCS)位(位 4-7)控制慢速充电器的选择。为了防止偶然的因素使之工作,只有 1010 模式才能使慢

速充电器工作,所有其它的模式将禁止慢速充电器。DS1302 上电时,慢速充电器被禁止。二极管选择(DS)位(位 2-3)选择是一个二极管还是两个二极管连接在 Vcc2 与 Vcc1 之间。如果 DS 为 01,那么选择一个二极管;如果 DS 为 10,则选择两个二极管。如果 DS 为 00 或 11,那么充电器被禁止,与 TCS 无关。RS 位(位0-1)选择连接在 Vcc2 与 Vcc1 之间的电阻。电阻选择(RS)位选择的电阻如下:

在这里插入图片描述

如果 RS 为 00,充电器被禁止,与 TCS 无关。

二极管和电阻的选择用户根据电池和超容量电容充电所需的最大电流决定。最大充电电流可以如下列

所说明的那样进行计算。假定 5V 系统电源加到 Vcc2 而超容量电容接至 Vcc1。再假设慢速充电器工作时在Vcc2 和 Vcc1 之间接有一个二极管和电阻 R1。因而最大电流可计算如下:

Imax =(5.0V-二极管压降)/R1

=(5.0V-0.7V)/2kΩ

= 2.2mA

显而易见,当超容量电容充电时,Vcc2 和 Vcc1 之间的电压减少,因而充电电流将会减小。


时序图

我们首先得给DS1302时钟模块写入时间和日期,然后呢这个时钟会自己走,我们之后只需要读取时间和日期即可。我们直接看时序图 编写代码

在这里插入图片描述

单字节写时序

数据输入

跟随在输入写命令字节的 8 个 SCLK 周期之后,在下 8 个 SCLK 周期的上升沿输入数据。如果有额外的SCLK 周期,它们将被忽略。输入从位 0 开始。

在这里插入图片描述
在这里插入图片描述

上面时序图是前8位是地址,后8位是数据。

我们根据上面的时序图 来编写 单字节写的一个函数

发现上面的


/*DS1302写单字节函数*/

void ds1302_write_byte(unsigned char addrOrData)

{

unsigned char i = 0;

for(i=0;i<8;i++)   

{

DAT = addrOrData & 0x01; //开始传输低位 

addrOrData = addrOrData >> 1;//右移一位

CLK = 1; //拉高时钟表示已经发送

CLK = 0; //拉低时钟准备继续放新的数据位

}

}


/*DS1302写函数*/

void ds1302_write(unsigned char addr,unsigned char data)

{

RST = 0; //RST拉低

SCLK = 0; //时钟SCLK也拉低

RST = 1; //准备开始写

ds1302_writeByte(addr); //写入要写的地址

ds1302_writeByte(dat); //写入地址的数据

RST = 0; //关闭 表示结束

}


看上面的图,比如我想写入时 为18点 时的写寄存器是84H 数据就是18点 但是DS1302存储格式为 BCD 码那就是 0x18。

那写入 时 为18点 的代码则是:


ds1302_write(0x84,0x18); //写入时  为 18点


单字节读时序

在这里插入图片描述
在这里插入图片描述

/*DS1302读单字节函数*/

unsigned char ds1302_read_byte(unsigned char data)

{

unsigned char i;

for(i=0;i<8;i++)

{

dat = dat >> 1; //右移一位 数据是先从低位开始

if(IO == 1)

dat = dat | 0x80; //1000 0000

else

dat = dat & 0x7f; //0111 1111

SCLK = 1; //时钟拉高表示这位已经结束

SCLK = 0; //时钟拉低开始接收新的数据位

}

return data;

}


/*DS1302读取数据函数*/

unsigned char ds1302_read_data(unsigned char addr)

{

unsigned char data; //用于存放接收的数据

RST = 0; //RST拉低

SCLK = 0; //时钟SCLK也拉低

RST = 1; //准备开始写

ds1302_write_byte(addr); //写入要读取的地址

data = ds1302_read_byte(data); //读取地址的数据

RST = 0;//关闭 表示结束

return data; //返回读取到的数据

}


我们想读取时 里面时间 看看现在是几点 时 读寄存器是85H


time = ds1302_read_data(0x85);


写保护寄存器

写保护寄存器的位 7 是写保护位。开始 7 位(位 0-6)置为零,在读操作时总是读出零。在对时钟或

功能 字节数 脉冲数

CLOCK 8 72

RAM 31 256

DS1302

RAM 进行写操作之前,位 7 必须为零。当它为高电平时,写保护位禁止对任何其它寄存器进行写操作。


时钟/日历多字节(Burst)方式

所谓的突发模式(BURST模式)就是一次性传送多个字节的时钟信号和RAM数据。比如我可以一次性把时间和日期写入,也可以一次性的读出时间和日期。

在这里插入图片描述

代码

部分代码呈现


main.c

#include

#include "lcd1602.h"

#include "ds1302.h"


void main()

{

lcd_init();   //初始化LCD1602 

ds1302_init();//初始化DS1302

while(1)

{

ds1302_burst_read(DS1302_READ_TIME); //读取日期和时间

lcd_display_dateAndTime(); //1602显示日期和时间

}

}


lcd1602.c

/*初始化LCD1602函数*/

void lcd_init()

{

unsigned char array1[] = "date:    -  -  ";

unsigned char array2[] = "time:  :  :  ";

write_com(CURSOR_RIGHT); //写入数据后光标自动右移 整屏不移动。 0x40(光标左移 整屏不移动)0x05(左移 整屏右移)0x07(右移 整屏右移)

write_com(CLOSE_DIS_CUR); //开显示功能 无光标 不闪烁

write_com(DIS_5X7); //数据总线8位 16X2显示 5*7点阵

write_com(CLEAR_SCREEN); //清屏 0000 0001


lcd_display_str(0,0,array1);  //第一行显示 date:    -  -  

lcd_display_str(0,1,array2);  //第二行显示 time:  :  :  


}


/*LCD1602 显示DS1302日期和时间 函数*/

void lcd_display_dateAndTime()   

{

lcd_display_byte(5,0,(time[7]>>4)+48); //显示年

lcd_display_byte(6,0,(time[7]&0x0f)+48);


lcd_display_byte(7,0,(time[6]>>4)+48); //显示年

lcd_display_byte(8,0,(time[6]&0x0f)+48);


lcd_display_byte(10,0,(time[4]>>4)+48); //显示月

lcd_display_byte(11,0,(time[4]&0x0f)+48);


lcd_display_byte(13,0,(time[3]>>4)+48); //显示日

lcd_display_byte(14,0,(time[3]&0x0f)+48);


lcd_display_byte(5,1,(time[2]>>4)+48); //显示时

lcd_display_byte(6,1,(time[2]&0x0f)+48);


lcd_display_byte(8,1,(time[1]>>4)+48); //显示分

lcd_display_byte(9,1,(time[1]&0x0f)+48);


lcd_display_byte(11,1,(time[0]>>4)+48); //显示秒

lcd_display_byte(12,1,(time[0]&0x0f)+48);


lcd_display_byte(14,1,(time[5]&0x0f)+48); //显示周


}


ds1302.c

#include "ds1302.h"


unsigned char time[8] = {0x00,0x45,0x19,0x18,0x10,0x01,0x21,0x20};//秒分时 日月周 年


/*DS1302单字节读数据函数*/

unsigned char ds1302_readByte(unsigned char dat)

{

unsigned char i = 0;

for(i=0;i<8;i++)  

{

dat = dat >> 1; //左移一次 低位开始 共有效左移7次

if(DAT == 1)

dat = dat | 0x80; //高位置1

else

dat = dat & 0x7F; //高位置0

CLK = 1; //时钟拉高表示这位已经结束

CLK = 0; //时钟拉低开始接收新的数据位

}

return dat;


}


/*DS1302单字节写地址或者数据函数*/

void ds1302_writeByte(unsigned char addrOrData)

{

unsigned char i = 0;

for(i=0;i<8;i++)   

{

DAT = addrOrData & 0x01; //开始传输低位 

addrOrData = addrOrData >> 1;//右移一位

CLK = 1; //拉高时钟表示已经发送

CLK = 0; //拉低时钟准备继续放新的数据位

}

}


/*DS1302时钟模块写命令函数*/

void ds1302_writeCom(unsigned char addr,unsigned char dat)

{

  RST = 0; //拉低RST

CLK = 0; //拉低时钟

RST = 1; //使能打开

ds1302_writeByte(addr); //写入要写的地址

ds1302_writeByte(dat); //写入地址的数据

RST = 0; //关闭 表示结束

}


/*DS1302时钟模块读数据函数*/

unsigned char ds1302_readData(unsigned char addr)

{

unsigned char dat = 0;

RST = 0; //拉低RST

CLK = 0; //拉低时钟

RST = 1; //打开使能

ds1302_writeByte(addr); //写入要读的地址

dat = ds1302_readByte(dat); //读取地址的数据

RST = 0; //关闭 表示结束

return dat; //返回读取到的数据

}


/*DS1302时钟模块读取日期和时间函数*/

void ds1302_read_DateAndTime()

{

time[0] = ds1302_readData(DS1302_READ_YEAR);  //读取年

time[1] = ds1302_readData(DS1302_READ_MONTH); //读取月

time[2] = ds1302_readData(DS1302_READ_DAY);   //读取日

time[3] = ds1302_readData(DS1302_READ_HOUR);  //读取时

time[4] = ds1302_readData(DS1302_READ_MINUTE);//读取分

time[5] = ds1302_readData(DS1302_READ_SECOND);//读取秒

time[6] = ds1302_readData(DS1302_READ_WEEK);  //读取周

}


/*DS1302时钟模块初始化函数*/

void ds1302_init()

{

RST = 0; //关闭RST

CLK = 0; //拉低时钟

ds1302_writeCom(DS1302_WRITE_PROTECT,0x00); //关闭写保护 这样才能进行写操作

ds1302_burst_write(DS1302_WRITE_TIME); //初始化全部时间

//ds1302_initTime(); //初始时间:2021年10月18日 19点45分00秒 周一

ds1302_writeCom(DS1302_WRITE_PROTECT,0x80); //开启写保护 只读模式

}


项目展示

请添加图片描述

关键字:51单片机  DS1302  时钟模块  LCD1602显示 引用地址:基于51单片机+DS1302时钟模块+LCD1602显示

上一篇:基于51单片机+LD3320语音模块+SYN6288语音合成——语音识别智能分类垃圾桶
下一篇:基于51单片机+DS18B20温度测温器+LCD1602显示

推荐阅读最新更新时间:2024-11-18 08:02

51单片机PWM控制电机
小时候玩的四驱车,给直流马达接通电源就嗤嗤的跑出去了。电机种类众多,就属控制直流电机最简单,只要对调正负极就能改变电机的转向。另外,直流电机负载能力强,适合做越野车的驱动电机。为了做可调速的越野车,就有了这篇文章。 电源电压输出是固定的,电机的转速也因此是固定的,为了调节电机的转速,就得改变电源电压的输出(为嘛要改变电机转速?举个简单的列子,双电机驱动小车-一边一个电机-如何实现转向?让两边轮胎上的速度不同即可)。how?用PWM调制的方法,把恒定的直流电源电压调制成频率一定宽度可变的脉冲电压序列,从而可以改变平均输出电压的大小,以调节电机的转速。电源电压在此处就是51MCU的引脚输出,4.5-5V,只要在引脚上产生频率可调
[单片机]
<font color='red'>51</font><font color='red'>单片机</font>PWM控制电机
51单片机+hx711电子秤
单片机源程序如下: #include reg52.h #include intrins.h #include string.h #include main.h #include LCD1602.h #include HX711.h #include eeprom52.h #define uchar unsigned char #define uint unsigned int unsigned long HX711_Buffer = 0; unsigned long Weight_Maopi = 0; unsigned long Weight_Maopi_0 = 0; long Weight_Shiwu =
[单片机]
<font color='red'>51</font><font color='red'>单片机</font>+hx711电子秤
基于51单片机的单个LED灯的设计
本设计旨在完成精确控制1个LED的亮灭状态而设计的,代码仅供参考。 代码: #include reg52.h #include intrins.h sbit LED=P1^0; void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 8; j = 1; k = 243; do { do { while (--k); } while (--j); } while (--i); } void main() { while(1) { LED
[单片机]
基于<font color='red'>51</font><font color='red'>单片机</font>的单个LED灯的设计
单片机成长之路(51基础篇) - 013 MCS-51单片机控制详解–T2M
T2CON:定时器控制寄存器 寄存器地址0C8H,位寻址0C8H~0CFH。 位地址 CF CE CD CC CB CA C9 C8 位符号 TF2 EXF2 RCLK TCLK EXEN2 TR2 C/T2 CP/RL2 TF2:T2溢出标记   当T2溢出时TF2=1,TD2只能用软件清除   当RCLK=1或TCLK=1时,TF2将不置位 EXF2:T2外部标记   当EXEN2=1时,T2EX/P1.1引脚上的负跳变引起T2的捕捉/重装操作,此时EXF2=1。在T2中断允许时,EXF2=1将引起中断,EXF2只能用软件清除。在T2的向上、向下计数模式下(DCEN=1)EXF2的置
[单片机]
4利用移位函数操作点亮流水灯
功能说明:利用移位函数操作点亮流水灯 程序源代码如下: #include reg52.h #include intrins.h #define uchar unsigned char #define uint unsigned int #define led P0 void delay (void) { uchar a,b; for(a=0;a 200;a++) for(b=0;b 200;b++); } void main(void) { uchar i,k; while(1) { k = 0xfe; for(i=0;i 8;i++) { led = k; de
[单片机]
4利用移位函数操作点亮流水灯
什么是MCS-51单片机、8051单片机51单片机
MCS-51单片机---是指美国INTEL公司生产的内核兼容的一系列单片机的总称。“MCS-51”也代表这一系列单片机的内核。这一系列单片机硬件结构和指令系统一致,包括8031、8051、8751、8032、8052、8752等基本型。 8051单片机---是MCS-51系列单片机中的一个基本型,是MCS-51系列中最早期、最典型、应用最广泛的产品,所以8051单片机也就成了MCS-51系列单片机的典型代表。 51单片机---51单片机是对目前所有兼容MCS-51指令系统的单片机的统称,包括INTEL MCS-51系列单片机、以及其他厂商生产的兼容MCS-51内核的增强型8051单片机。只要和MCS-51内核兼容的
[单片机]
PIC单片机以及51单片机和AVR单片机的IO口操作方法介绍
对于pic单片机的学习,很多朋友总是能充满激情,不断利用闲余时间研究pic单片机的各类技术。而谈及pic单片机,必须牵扯至51、AVR单片机。因此本文中,将探讨pic单片机以及51、AVR单片机对于IO口的操作。对于本文,希望大家认真研读,以在pic单片机的学习之路上更为精进。 一.51单片机IO口的操作 51单片机IO口的结构比较简单,每个IO口只有一个IO口寄存器Px,而且这个寄存器可以位寻址,操作起来是所有单片机里最简单的,可以直接进行总线操作也可以直接进行位操作,这也是51单片机之所以成为经典的原因之一。下例的运行坏境为Keil软件,器件为AT89S52。 #i nclude sbit bv=P2^0;//定义位变量,
[单片机]
PIC<font color='red'>单片机</font>以及<font color='red'>51</font><font color='red'>单片机</font>和AVR<font color='red'>单片机</font>的IO口操作方法介绍
89C51单片机的接线及调试
拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。 1、电源:这当然是必不可少的了。单片机使用的是5V电源,其中正极接40管脚,负极(地)接20管脚。 2、振蒎电路:单片机是一种时序电路    拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。 1、 电源:这当然是必不可少的了。单片机使用的是5V电源,其中正极接40管脚,负极(地)接20管脚。 2、振蒎电路:单片机是一种时序电路,必须供给脉冲信号才能正常工作,在单片机内部已集成了振荡器,使用晶体振荡器,接18、19脚。只要买来晶体震荡器,电容
[单片机]
89C<font color='red'>51</font><font color='red'>单片机</font>的接线及调试
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved