实时时钟芯片DS1302在STM32系列使用详解

目录

1.  DS1302简介

1.1  特点

1.2  引脚

1.3  工作原理

1.4  硬件电路

1.5  时序图

1.5.1  读数据

1.5.2  写数据

2.  DS1302使用

3.  代码编写

3.1  时钟初始化

3.2  单片机引脚配置

3.3  DS1302写操作配置

3.4  DS1302读操作配置

3.5  初始化DS1302

3.6  读取时钟信息


1.  DS1302简介

1.1  特点

(1)可对秒,分,时,日,周,月,和年进行计数,对于小于 31 天的月,月末的日期自动进行调整,还具有闰年校正的功能;

(2)用于高速数据暂存的 31 字节的非易失性静态 RAM;

(3)时钟可以采用 24 小时格式或带 AM(上 午)/PM(下午)的 12 小时格式;

(4)宽工作电压:2.0V~5.5V;

(5)2.5V时耗小于300nA;

(6)用于时钟或RAM数据读/写的单字节或多字节数据传输方式;

(7)简单的3线接口与单片机通信;

与时钟/RAM 通信仅需 3 根线:

  • RST(复位)
  • I/O(数据线)
  • SCLK(串行时钟)

(8)TTL兼容(Vcc=5V);

(9)可选地工业温度范围-40℃至85℃;

(10)封装:DIP8和SOP8。

1.2  引脚

管脚序号 符号 功能
1 V_{CC2} 主用电源
2 X1 32.768kHz晶振
3 X2 32.768kHz晶振
4 GND
5 RST 复位
6 I/O 数据输入/输出
7 SCLK 串行时钟输入
8 V_{CC1} 备用电源

1.3  工作原理

        如下图,RST 信号有效后,移位寄存器单元会在 SCLK 同步脉冲信号的控制下从 I/O 上串行接收 8 位指令字节,然后将 8 位指令字节进行串并转换并送至 ROM 指令译码单元。由 ROM 指令译码单元对 8 位指令字节进行译码,以决定内部寄存器的地址以及读写状态。然后在接下来的 SCLK 同步脉冲信号的控制下将 8 位数据写进或者读出相应的寄存器。数据传送也可以采用多字节方式,先将 8 位相应的指令字节写入,然后在连续的 SCLK 的脉冲信号同步下,将数据字节连续写入或读出日历/时钟寄存器(或者RAM 单元)。SCLK 脉冲的个数在单字节方式下为 8 加 8,在多字节方式下为 8 加最大可达到 248 的数。

1.4  硬件电路

1.5  时序图

1.5.1  读数据

1.5.2  写数据

2.  DS1302使用

每一数据传送由命令字节初始化:

有效位 作用
MSB(位7) 必须为逻辑1,如果为0,则禁止写DS1302
RAM/CLK(位6) 逻辑0:指定时钟/日历数据
逻辑1:指定RAM数据
A4\A3\A2\A1\A0(位1~5) 指定进行输入或输出特定寄存器
LSB(位0) 逻辑0:制定进行写操作(输入)
逻辑1:指定进行读操作(输出)

命令字节总是从最低有效LSB位0开始输入。

        通过把 RST 输入驱动至高电平来启动所有的数据传送。

RST 输入有两种功能:

接通控制逻辑:当RST信号被接通时,控制逻辑被激活,允许地址和命令序列被送入移位寄存器。

中止数据传送:RST信号可以在任何时刻中止正在进行的数据传送。

寄存器 0:最高位 CH 是一个时钟停止标志位。停止后为1,正常工作为0。如果 Vcc1 悬空或者是电池没电了,当我们下次重新上电时,读取这一位,那这一位就是 1,我们可以通过这一位判断时钟在单片机系统掉电后是否还正常运行。剩下的 7 位高 3 位是秒的十位,低 4 位是秒的个位。

寄存器 1:最高位未使用,剩下的 7 位中高 3 位是分钟的十位,低 4 位是分钟的个位。

寄存器 2:bit7 是 1 的话代表是 12 小时制,0 代表是 24 小时制;bit6 固定是 0,bit5 在 12 小时制下 0 代表的是上午,1 代表的是下午,在 24 小时制下和 bit4 一起代表了小时的十 位,低 4 位代表的是小时的个位。

寄存器 3:高 2 位固定是 0,bit5 和 bit4 是日期的十位,低 4 位是日期的个位。

寄存器 4:高 3 位固定是 0,bit4 是月的十位,低 4 位是月的个位。

寄存器 5:高 5 位固定是 0,低 3 位代表了星期。

寄存器 6:高 4 位代表了年的十位,低 4 位代表了年的个位。请特别注意,这里的 00~ 99 指的是 2000 年~2099 年。

寄存器 7:最高位一个写保护位,如果这一位是 1,那么是禁止给任何其它寄存器或者 那 31 个字节的 RAM 写数据的。因此在写数据之前,这一位必须先写成 0。

3.  代码编写

3.1  时钟初始化

        DS1302写入和读取时分秒的地址命令“秒分时日月周年最低位读写位:

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

        DS1302时钟初始化2013年1月1日星期二12点00分00秒,存储顺序“秒分时日月周年”,存储格式为BCD码:

uint8_t TIME[7] = {0x00, 0x47, 0x21, 0x29, 0x3, 0x03, 0x23};

3.2  单片机引脚配置

配置成推挽输出模式:

void DS1302_OUT_GPIO_INIT(void)
{

	GPIO_InitTypeDef  GPIO_InitStructure;  

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
 
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//
	GPIO_Init(GPIOA, &GPIO_InitStructure);

}

数据引脚配置成上拉输入模式:

void DS1302_IN_GPIO_INIT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;  

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 ;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

引脚宏定义:

#define DSIO_H   GPIO_SetBits(GPIOA,GPIO_Pin_0)
#define DSIO_L   GPIO_ResetBits(GPIOA,GPIO_Pin_0)
#define RST_H    GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define RST_L    GPIO_ResetBits(GPIOA,GPIO_Pin_1)
#define SCLK_H   GPIO_SetBits(GPIOA,GPIO_Pin_2)
#define SCLK_L   GPIO_ResetBits(GPIOA,GPIO_Pin_2)
#define GET_DSIO  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)

3.3  DS1302写操作配置

void Ds1302Write(uint8_t addr, uint8_t dat)
{
	uint8_t n;
    DS1302_OUT_GPIO_INIT();
	RST_L;
	Delay1us();//加个1us的延时
   
	SCLK_L;//先将SCLK置低电平。
	Delay1us();
	RST_H; //然后将RST(CE)置高电平。
	Delay1us();

	for (n=0; n<8; n++)//开始传送八位地址命令
	{
        if(addr & 0x01)
        {
            DSIO_H;//数据从低位开始传送
        }
        else
        {
            DSIO_L;
        }
		addr >>= 1;
		SCLK_H;//数据在上升沿时,DS1302读取数据
		Delay1us();
		SCLK_L;
		Delay1us();
	}
	for (n=0; n<8; n++)//写入8位数据
	{
		if(dat & 0x01)
        {
            DSIO_H;//数据从低位开始传送
        }
        else
        {
            DSIO_L;
        }
		dat >>= 1;
		SCLK_H;//数据在上升沿时,DS1302读取数据
		Delay1us();
		SCLK_L;
		Delay1us();	
	}	
		 
	RST_L;//传送数据结束
	Delay1us();
}

3.4  DS1302读操作配置

uint8_t Ds1302Read(uint8_t addr)
{
	uint8_t n,dat,dat1;
	RST_L;
	Delay1us();

	SCLK_L;//先将SCLK置低电平。
	Delay1us();
	RST_H;//然后将RST(CE)置高电平。
	Delay1us();
    
	for(n=0; n<8; n++)//开始传送八位地址命令
	{
		if(addr & 0x01)
        {
            DSIO_H;//数据从低位开始传送
        }
        else
        {
            DSIO_L;
        }
		addr >>= 1;
		SCLK_H;//数据在上升沿时,DS1302读取数据
		Delay1us();
		SCLK_L;//DS1302下降沿时,放置数据
		Delay1us();
	}
	Delay1us();
    DS1302_IN_GPIO_INIT();
	for(n=0; n<8; n++)//读取8位数据
	{
		dat1 = GET_DSIO;//从最低位开始接收
		dat = (dat>>1) | (dat1<<7);
		SCLK_H;
		Delay1us();
		SCLK_L;//DS1302下降沿时,放置数据
		Delay1us();
	}
    DS1302_OUT_GPIO_INIT();
	RST_L;
	Delay1us();	//以下为DS1302复位的稳定时间,必须的。
	SCLK_H;
	Delay1us();
	DSIO_L;
	Delay1us();
	DSIO_H;
	Delay1us();
	return dat;	
}

3.5  初始化DS1302

void Ds1302Init(void)
{
	uint8_t n;
	Ds1302Write(0x8E,0X00);		 //禁止写保护,就是关闭写保护功能
	for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
	{
		Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);	
	}
	Ds1302Write(0x8E,0x80);		 //打开写保护功能
}

3.6  读取时钟信息

void Ds1302ReadTime(void)
{
	uint8_t n;
	for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
	{
		TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
	}
		
}

STM32学习笔记_时光の尘的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/MANONGDKY/article/details/143248212