单片机第一季:零基础11——实时时钟DS1302

这篇具有很好参考价值的文章主要介绍了单片机第一季:零基础11——实时时钟DS1302。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1,DS1302 时钟芯片介绍 

2,BCD码介绍 

3,涉及到的寄存器 

3.1,控制寄存器

3.2,日历/时钟寄存器 

3.3,DS1302 的读写时序 

4,相关代码 


这一章我们来学习DS1302 时钟芯片,该芯片是3 线SPI 接口,所以需要使用51单片机的3 个IO 口模拟SPI 时序与DS1302 时钟芯片通信,将时钟日历数据读取出来。开发板上集成了1 个DS1302 时钟模块,可使用它设计一个多功能电子时钟。本章要实现的功能是:系统运行时,数码管上显示电子时钟时分秒,格式为“XX-XX-XX”。

1,DS1302 时钟芯片介绍 

DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、周、月、年的信息,每月的天数和闰年的天数可自动调整。时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三根通信线:①RES复位②I/O 数据线③SCLK 串行时钟。时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信。DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW。 

DS1302 由DS1202 改进而来增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vcc1 为可编程涓流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域下面。 

主要的性能指标:
★ 实时时钟具有能计算2100 年之前的秒、分、时、日、星期、月、年的能力,还有闰年调整的能力;
★ 31 个8 位暂存数据存储RAM;
★ 串行I/O 口方式使得管脚数量最少;
★ 宽范围工作电压2.0~5.5V;
★ 工作在2.0V 时,电流小于300nA;
★ 读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式;
★ 8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配;
★ 简单3 线接口;
★ 与TTL 兼容Vcc=5V;
★ 可选工业级温度范围-40~+85; 

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

1,VCC2:主电源引脚
2,X1、X2:DS1302 外部晶振引脚,通常需外接32.768K 晶振
3,GND:电源地
4,CE:使能引脚,也是复位引脚(新版本功能变)
5,I/O:串行数据引脚,数据输出或者输入都从这个引脚
6,SCLK:串行时钟引脚
7,VCC1:备用电源 

51单片机和DS1302芯片之间的通讯是SPI,SPI的主要特点:3线or4线、同步、主从、串行;

3线or4线: CE、I/O、SCLK,3线I/O是一根线,4线I/O是两根线;

同步:与UART的异步通讯相比,需要SCLK同步信息的发送和接收;

主从:谁来发出SCLK同步信号; 

串行:在数据线上按位传输数据; 

DS1302是变种SPI,通过SCLK和I/O相互配合,发送和接收信息。SCLK在上升沿前,主机通过I/O口发送数据,DS1302在上升沿是接收;SCLK在下降沿后,DS1302通过I/O口发送数据,主机接收。

 SPI:SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。

DS1302参考: 

DS1302介绍

2,BCD码介绍 

为什么要介绍BCD码?因为从DS1302芯片读出来的数据是BCD 码形式,当使用串口助手查看数据时看到的是十进制形式,但其本质上是十六进制数据。

BCD码是一种数字编码,这种计数编码有个特点:很像10进制和16进制的结合。看起来很像10进制(29下来是30而不是2A),BCD码实际是用十六进制来表示的(BCD码的21其实在计算机中就是0x21)。BCD码中只有0-9,而没有ABCDEF等字目。 

综合来讲:BCD码其实就是看起来很像十进制数的十六进制数。意思就是:BCD码本质上是十六进制数,但是因为他没有ABCDEF,所以看起来很像十进制数。 

DS1302使用BCD码来处理时间信息,对单片机来说是16进制方便单片机处理,对人来说可以认为是10进制,同时方便单片机和人来识别信息。

例如:

如果把一个数21分成两个数,对于十进制的21,需要通过21/10得到2,通过21%10得到1; 

对于十六进制的21,分成两个数,通过0x21>>4的得到2 ,通过0x21&0x0F得到1;

对于计算机来说,移位和与操作的复杂度优于除和取余。 

3,涉及到的寄存器 

操作DS1302 的大致过程,就是将各种数据写入DS1302 的寄存器,以设置它当前的时间的格式。然后使DS1302 开始运作,DS1302 时钟会按照设置情况运转,再用单片机将其寄存器内的数据读出。 

3.1,控制寄存器

控制寄存器用于存放DS1302 的控制命令字,DS1302 的RST 引脚回到高电平后写入的第一个字节就为控制命令。它用于对DS1302 读写过程进行控制,格式如下: 

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

上图是DS1302 的寄存器样式,我们看到:
1、第7 位永远都是1;
2、第6 位,1 表示RAM,寻址内部存储器地址;0 表示CK,寻址内部寄存器;

3、第5 到第1 位,为RAM 或者寄存器的地址;
4、最低位,高电平表示RD,即下一步操作将要“读”;低电平表示W,即下一步操作将要“写”。

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

比如要读秒寄存器则命令为1000 0001,反之写为1000 0000,要注意其含义。 

3.2,日历/时钟寄存器 

DS1302 共有12 个寄存器,其中有7 个与日历、时钟相关,存放的数据为BCD码形式 。

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

秒寄存器:低四位为秒的个位,高的次三位为秒的十位。最高位CH 为DS1302 的运行标志,当CH=0 时,DS1302 内部时钟运行,反之CH=1 时停止; 

小时寄存器:时寄存器。最高位为12/24 小时的格式选择位,该位为1 时表示12 小时格式。当设置为12 小时显示格式时,第5 位的高电平表示下午(PM);而当设置为24 小时格式时,第5 位位具体的时间数据。 

写保护寄存器:当该寄存器最高位WP 为1 时,DS1302 只读不写,所以要在往DS1302 写数据之前确保WP 为0。 

慢充电寄存器(涓细电流充电)寄存器:我们知道,当DS1302 掉电时,可以马上调用外部电源保护时间数据。该寄存器就是配置备用电源的充电选项的。其中高四位(4 个TCS)只有在1010 的情况下才能使用充电选项;低四位的情况与DS1302 内部电路有关。

思考:日历/时钟寄存器中还存储了除了时间数据之外的其它数据,这些数据在读写时是如何操作的? 

3.3,DS1302 的读写时序 

在控制指令字输入后的下一个SCLK 时钟的上升沿时,数据被写入DS1302,数据输入从低位(位0)开始。同样,在紧跟8 位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302 的数据,读出数据时从低位0 位到高位7。其时序图如下所示: 

单片机第一季:零基础11——实时时钟DS1302,单片机,单片机,嵌入式硬件

上图就是DS1302 的三个时序:复位时序,单字节写时序,单字节读时序;CE(RST):复位时序,即在RST 引脚产生一个正脉冲,在整个读写器件,RST 要保持高电平,一次字节读写完毕之后,要注意把RST 返回低电平准备下次读写周期;

单字节读时序:注意读之前还是要先对寄存器写命令,从最低位开始写;可以看到,写数据是在SCLK 的上升沿实现,而读数据在SCLK 的下降沿实现。所以,在单字节读时序中,写命令的第八个上升沿结束后紧接着的第八个下降沿就将要读寄存器的第一位数据读到数据线上了!这个就是DS1302 操作中最特别的地方。当然读出来的数据也是最低位开始。 

单字节写时序:两个字节的数据配合16 个上升沿将数据写入即可。 

程序注意事项:
★要记得在操作DS1302 之前关闭写保护;
★注意用延时来降低单片机的速度以配合器件时序;

★DS1302 读出来的数据是BCD 码形式,要转换成我们习惯的10 进制,转换
方法在源程序里;
★读取字节之前,将IO 设置为输入口,读取完之后,要将其改回输出口;
★在写程序的时候,建议实现开辟数组(内存空间)来集中放置DS1302 的
一系列数据,方便以后扩展键盘输入。 

4,相关代码 

ds1302底层时序代码,分为ds1320.c和ds1302.h两个文件:

 ds1302.h

#ifndef  __DS1302_H__
#define  __DS1302_H__

//从ds1302的内部寄存器addr写入一个值value
void ds1302_write_reg(unsigned char addr, unsigned char value);
//从ds1302的内部寄存器addr读出一个值,作为返回值
unsigned char ds1302_read_reg(unsigned char addr);



#endif

ds1320.c

#include "ds1302.h"

#include <reg51.h>


sbit DSIO	= P3^4;
sbit RST	= P3^5;
sbit SCLK	= P3^6;


void delay(void)
{
	unsigned char i;
	for (i=0; i<3; i++);
}

//从ds1302的内部寄存器addr写入一个值value
void ds1302_write_reg(unsigned char addr, unsigned char value)
{
	unsigned char i,dat;
	//第一部分:时序初始化
	RST = 0;
	delay();
	SCLK = 0;
	delay();
	RST = 1;
	delay();

	//第二部分:写入地址
	for(i=0; i<8; i++)
	{
	   dat = addr & 0x01; //取地址的低位
	   DSIO = dat;
	   addr >>=1;
	   SCLK = 1;		  //创造一个上升沿,让ds1302将信号线上的值读走
	   delay();
	   SCLK = 0;
	}

    //第三步:写入数据
	for(i=0; i<8;i++)
	{
	   dat = value & 0x01; //取数据的低位
	   DSIO = dat;
	   value >>=1;
	   SCLK = 1;		  //创造一个上升沿,让ds1302将信号线上的值读走
	   delay();
	   SCLK = 0;		
	}

	//第四部分:时序结束
	RST = 0;
	delay();
	SCLK = 0;
	delay();


}


// 从ds1302的内部寄存器addr读出一个值,作为返回值
unsigned char ds1302_read_reg(unsigned char addr)
{
	unsigned char i = 0;
	unsigned char dat = 0; 		// 用来存储读取到的一字节数据的
	unsigned char tmp = 0;

	// 第1部分: 时序起始
	SCLK = 0;
	delay();
	RST = 0;
	delay();
	RST = 1;  		// SCLK为低时,RST由低变高,意味着一个大的周期的开始
	delay();
	// 第2部分: 写入要读取的寄存器地址,addr
	for (i=0; i<8; i++)
	{
		dat = addr & 0x01;	 	// SPI是从低位开始传输的
		DSIO = dat;	 			// 把要发送的bit数据丢到IO引脚上去准备好
		SCLK = 1;		 		// 制造上升沿,让DS1302把IO上的值读走
		delay();				// 读走之后,一个小周期就完了
		SCLK = 0;				// 把SCLK拉低,是为了给下一个小周期做准备
		delay();
		addr >>= 1;	   			// 把addr右移一位
	}
	// 第3部分: 读出一字节DS1302返回给我们的值
	dat = 0;
	for (i=0; i<8; i++)
	{
	// 在前面向ds1302写入addr的最后一个bit后,ds1302就会将读取到的寄存器值
	// 的第一个bit放入到IO引脚上,所以我们应该先读取IO再制造下降沿然后继续
	// 读取下一个bit
		tmp = DSIO;
		dat |= (tmp << i);		// 读出来的数值是低位在前的
		SCLK = 1;  				// 由于上面SCLK是低,所以要先拉到高
		delay();
		SCLK = 0;				// 拉低SCLK制造一个下降沿
		delay();
	}
	// 第4部分: 时序结束
	SCLK = 0;				  	// SCLK拉低为了后面的周期时初始状态是对的
	delay();
	RST = 0;					// RST拉低意味着一个大周期的结束
	delay();

	// 第5部分:解决读取时间是ff的问题
	DSIO = 0;

	return dat;
}


通过串口接收时钟数据,分为uart.c和uart.h两个文件:

 uart.h

#ifndef __UART_H__
#define __UART_H__


//串口初始化
void uart_init();
//串口发送数据
void uart_send_byte(unsigned char c);


#endif

uart.c

#include "uart.h"
#include <reg51.h>


void uart_init()
{
	TMOD|=0X20; //设置计数器工作方式2
	SCON=0X50; //设置为工作方式1
	PCON=0X80; //波特率加倍
	TH1=0xFA; //计数器初始值设置
	TL1=0xFA;
	ES=1; //打开接收中断
	EA=1; //打开总中断
	TR1=1; //打开计数器
}

void uart_send_byte(unsigned char c)
{
   // 第1步,发送一个字节
   SBUF = c;

   // 第2步,先确认串口发送部分没有在忙
   while (!TI);

   // 第3步,软件复位TI标志位
   TI = 0;
}

main函数:

包括ds1302的上层时序,读出时钟数据和写入时钟数据,以及调用uart函数。文章来源地址https://www.toymoban.com/news/detail-603626.html

#include <reg51.h>
#include <intrins.h>

#include "ds1302.h"
#include "uart.h"

unsigned char code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
unsigned char code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
unsigned char time[7]={0};


void delay1s(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}


void ds1302_read_time(void)
{
	unsigned char i = 0;
	for (i=0; i<7; i++)
	{
		time[i] = ds1302_read_reg(READ_RTC_ADDR[i]);
	}
}

void ds1302_write_time(void)
{
	unsigned char i = 0;

	// 准备好要写入的时间
	time[0] = 0x24;				// 对应 24s
	time[1] = 0x39;				// 对应 39m
	time[2] = 0x11;				// 对应 11h
	time[3] = 0x06;				// 对应 6日
	time[4] = 0x12;				// 对应 12月
	time[5] = 0x02;				// 对应 星期2
	time[6] = 0x16;				// 对应 2016年

	ds1302_write_reg(0x8E, 0x00);	// 去掉写保护
	for (i=0; i<7; i++)
	{
		ds1302_write_reg(WRITE_RTC_ADDR[i], time[i]);
	}
	ds1302_write_reg(0x8E, 0x80);	// 打开写保护
}


void main()
{


	uart_init();

	ds1302_write_time();



	while(1)
	{
	   int i = 0;
	   ds1302_read_time();
	   for(i=0;i<7;i++) 
	   {
	   	  uart_send_byte(time[i]);
	   }

	   delay1s();
	}

}



到了这里,关于单片机第一季:零基础11——实时时钟DS1302的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机第一季:零基础13——AD和DA转换

    51 单片机系统内部运算时用的全部是数字量,即0 和1,因此对单片机系统而言,无法直接操作模拟量,必须将模拟量转换成数字量。所谓数字量,就是用一系列0 和1 组成的二进制代码表示某个信号大小的量。用数字量表示同一个模拟量时,数字位数可以多也可以少,位数越多

    2024年02月13日
    浏览(44)
  • 单片机第一季:零基础6——定时器和计时器

    目录 1,单片机定时器原理 2,51单片机定时器/计数器结构 3,定时器配置  4,示例代码-通过定时器控制LED灯间隔1s闪烁  51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。 定时器/计数器和单片机的CPU 是相互独立的。定时器/计数器工作

    2024年02月15日
    浏览(53)
  • 单片机第一季:零基础9——直流电机和步进电机

    目录 1,直流电机 2,步进电机  直流电机是指能将直流电能转换成机械能(直流电动机)或将机械能转换成直流电能(直流发电机)的旋转电机。它是能实现直流电能和机械能互相转换的电机。当它作电动机运行时是直流电动机,将电能转换为机械能;作发电机运行时是直流

    2024年02月16日
    浏览(39)
  • 单片机第一季:零基础12——I2C和EEPROM

    目录 1,EEPROM 2,I2C  2.1,I2C物理层  2.2,I2C协议层  3,AT24C02介绍  4,代码  为什么需要EEPROM? 单片机内部的ROM只能在程序下载时进行擦除和改写,但是程序运行本身是不能改写的。单片机内部的RAM中的数据程序运行时可以改,但是掉电就丢失了。有时候我们有一些数据要

    2024年02月14日
    浏览(43)
  • 51单片机实时时钟显示

    51单片机+DS1302+DS18B20+LCD12864 用的IIC通信,写的一个ds3231时钟模块的程序,可更改时间,下面是.h文件里面的部分代码 #ifndef __ds3231_h #define _ ds3231_h #include reg51.h #define uchar unsigned char #define uint unsigned int extern uchar day2,Htemp2,Mtemp2,Stemp2; //星期,时分秒 extern ucharYtemp2,Mtemp2,Dtemp2,Ttem

    2024年02月09日
    浏览(36)
  • 【单片机】13-实时时钟DS1302

    (rtc for real time clock) (1)时间点和时间段的概念区分 (2)单片机为什么需要时间点【一定的时间点干什么事情】 (3)RTC如何存在于系统中(单片机内部集成 or 单片机外部扩展【DS1302】) 1.数据手册 DS1302中文数据手册 - 豆丁网 2. SPI数字接口 访问 SPI通信协议【DS1302也使用

    2024年02月07日
    浏览(43)
  • 51单片机(十)DS1302实时时钟

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月03日
    浏览(46)
  • 【单片机】STM32单片机,RTC实时时钟,STM32F103C8T6,程序,万年历,数字时钟

    我以STM32F103C8T6为例,但STM32F103的RTC是通用的,STM32F103C8T6有一个原理图: https://qq742971636.blog.csdn.net/article/details/131288390 用纽扣电池给VBAT供电(要共地),即可实现掉电后依旧走时的能力。 主要特性(来源于STM32中文参考手册V10.pdf): 记得加标准库文件: 串口接收:

    2024年02月11日
    浏览(53)
  • 【STM32】基础知识 第一课 单片机简介

    单片机 (Single-Chip Microcomputer) 单品微型计算机, 是一种集成电路芯片. 电脑 vs 单片机: 电脑 单片机 CPU CPU 内存 SRAM 硬盘 Flash 主板 外设 SRAM 静态随机读取器 (Static Random-Access Memory): SRAM 是随机存储器的一种, 属于静态数据, 这类存储器要是维持电源, 里面存储的信息就可以恒常维持

    2024年02月11日
    浏览(93)
  • 单片机第三季-第一课:STM32基础

    STM32系列分类: 型号命名原则: STM32F103系列: 涉及到的几个概念: DMA:Direct Memory Access,直接存储器访问。DMA传输将数据从一个地址空间复制到另一个地址空间,提供外设和存储器或存储器和存储器之间的高速数据传输; 2.0到3.6V供电,IO口可以兼容5V电压; 与51单片机不同

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包