STM32驱动DS1302时钟模块(串口和OLED显示)

简介

DS1302 是 DALLAS 公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和 31 字节静态 RAM 通过简 单的串行接口与单片机进行通信 实时时钟/日历电路提供秒、分、时、日、日期、月和年的信息每月的天数和闰年的天数可自动调整,时钟操作可通过 AM/PM 指示决定采用 24 或 12 小时格式。DS1302 与单片机之间能简单地采用同步串行的方式进行通信。时钟/RAM 的读/写数据以一个字节或多达 31 个字节的字符组方式通信。DS1302 是由DS1202 改进而来增加了以下的特性: 双电源管脚用于主电源和备份电源供应, VCC为可编程涓流充电电源附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域。
在这里插入图片描述

性能特征

(1)实时时钟具有能计算 2100 年之前的秒分时日日期星期月年的能力还有闰年调整的能力。
(2)31×8 位暂存数据存储 RAM
(3)串行 I/O 口方式使得管脚数量最少
(4)宽范围工作电压 2.0 5.5V
(5)工作电流 2.0V 时,小于 300nA
(6)读/写时钟或 RAM 数据时,有两种传送方式:单字节传送和多字节传送(字符组方式)
(7)简单 3 线接口:RES(复位)、I/O(数据),SCLK(串行时钟)
(8)与TTL兼容Vcc=5V
(9)可选工业级温度范围:-40+85℃

原理图

在这里插入图片描述

命令字节

在这里插入图片描述

有效位 功能
位7 必须为逻辑1;如为0,将禁止写入DS1302
位6 逻辑0:指定时钟/日历数据 逻辑1:指定RAM数据
位1-5 指定输入或输出寄存器
位0 逻辑0:写操作(输入)逻辑1:读操作(输出)

注意:命令字节总是从LSB(位0)开始输入

复位和时钟控制

驱动RST输入高启动所有数据传输。RST输入有以下两个功能:

其一,RST打开控制逻辑,允许访问地址/命令序列的移位寄存器。
其二,RST信号提供终止单字节或多字节数据传输的方式。

时钟周期是一个上升沿和下降沿的序列。对于数据输入,数据必须在时钟上升沿期间有效,数据位在时钟下降沿上输出。如果RST输入低,所有数据传输终止,I/0引脚进入高阻抗状态。如下图显示了数据传输。在上电时,RST必须为逻辑0,直到VCC>2.0V。另外,当RST被驱动到逻辑1状态时,SCLK必须处于逻辑0。

在这里插入图片描述

数据输入

在输入写命令字节的8个SCLK周期之后,在下一个8个SCLK周期的上升沿上输入一个数据字节。如果无意中发生额外的SCLK周期,则忽略它们。数据从0位开始输入。

数据输出

在输入读命令字节的8个SCLK周期之后,在接下来的8个SCLK周期的下降沿上输出一个数据字节。注意,要传输的第一个数据位发生在写入命令字节的最后- -位之后的第一个下降沿上。额外的SCLK周期重新传输数据字节,如果他们无意中发生,只要RST保持高。此操作允许连续突发模式读取能力。此外,I/O引脚在SCLK的每个上升沿上都是三态。数据从0位开始输出。

突发模态

突发模式可以指定时钟/日历或RAM寄存器通过寻址位置31小数(地址/命令位1到5逻辑1)。和以前一样,第6位指定时钟或RAM,第0位指定读或写。时钟/日历寄存器中的位置9到31或RAM寄存器中的位置31没有数据存储容量。以突发方式读写,从地址0的0位开始。
当以突发模式写入时钟寄存器时,必须先写入前8个寄存器,以便传输数据。但是,当以突发模式写入RAM时,没有必要为数据传输写入所有31个字节。无论是否写入所有31个字节,写入的每个字节都将被传输到RAM中。

寄存器地址

在这里插入图片描述

寄存器1:Bit7被定义为时钟停止(CH)标志。当该位设置为逻辑1时,时钟振荡器停止,DS1302被置于低功耗待机模式。当这个位写入逻辑0时,时钟将启动。Bit4-Bit6代表秒的十位,Bit0-Bit3则表示秒的个位。

寄存器2:Bit7未使用,Bit4-Bit6代表分钟的十位,则Bit0-Bit3表示分钟的个位。

寄存器3:在12或24小时模式下,Bit7为逻辑1时代表12小时模式,为逻辑0时代表24小时模式;Bit6固定为0,在24小时模式下,Bit5和Bit4一起代表小时的十位,在12小时模式下,Bit5为逻辑0时,代表AM,为逻辑1时代表PM;Bit0-Bit3表示小时的个位。

寄存器4:Bit6和Bit7固定为0,Bit4和Bit5代表日期的十位,则Bit0-Bit3代表日期的个位。

寄存器5:Bit5-Bit7固定为0,Bit4代表月份的十位,Bit0-Bit3则表示月份的个位。

寄存器6:Bit3-Bit7固定为0,Bit0-Bit2表示星期的个位。

寄存器7:Bit4-Bit7表示年的十位,Bit0-Bit3代表年的个位。

寄存器8:Bit7位是写保护位,前7位(Bit0-B it6)被强制为0,读取时总是读0。当Bit7为逻辑1时,写保护位阻止对任何其他寄存器的写操作,所以在对时钟或RAM进行任何写操作之前,Bit7必须为0。

时序图

读取数据传输
在这里插入图片描述
写入数据传输
在这里插入图片描述

接线图

STM32 DS1302 OLED
5V VCC VCC
GND GND GND
PA7 CLK
PA6 SDA -
PA5 RST -
PB11 - SCL
PB10 - SDA

代码

DS1302.c (部分代码)

void DS1302_Init(void)// 写入时钟数据
{
	DS1302_wirte_rig(0x8e,0x00);//关闭写保护
	DS1302_wirte_rig(0x80,0x00);//seconds00秒
	DS1302_wirte_rig(0x82,0x30);//minutes30分
	DS1302_wirte_rig(0x84,0x15);//hours15时
	DS1302_wirte_rig(0x86,0x17);//date17日
	DS1302_wirte_rig(0x88,0x03);//months03月
	DS1302_wirte_rig(0x8a,0x01);//days星期一
	DS1302_wirte_rig(0x8c,0x25);//year2025年
	DS1302_wirte_rig(0x8e,0x80);//开启写保护
}

初始化DS1302,初始化时钟时间为“2025年3月17日15时30分,星期一”。确保后续时钟正常运行计时

void DS1302_read_time(void)
{
	read_time[0]=DS1302_read_rig(0x81);//读秒
	read_time[1]=DS1302_read_rig(0x83);//读分
	read_time[2]=DS1302_read_rig(0x85);//读时
	read_time[3]=DS1302_read_rig(0x87);//读日
	read_time[4]=DS1302_read_rig(0x89);//读月
	read_time[5]=DS1302_read_rig(0x8B);//读星期
	read_time[6]=DS1302_read_rig(0x8D);//读年
}

读取实时时间,按手册的寄存器说明,读取秒、分、时、日、月、星期和年,以便输出显示。

main.c

#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "ds1302.h"
#include "timer.h"
char realTime[50];
int main(void)
{ 
	
  u16 ii=0;
	delay_init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	DS1302_GPIO_Init();	
    DS1302_Init();						//时间设置
    DS1302_read_realTime();   //读取实时数据 
	LED_Init();
	USART1_Config();//串口初始化
	OLED_Init();                                  //屏幕初始化
	OLED_Clear();
    
  while(1)
  {
		
	    DS1302_read_realTime();    //读取此时时刻
	    printf("%d  ",TimeData.year);
	    printf("年");
	    printf("%d  ",TimeData.month);
	    printf("月");
	    printf("%d  ",TimeData.day);
	    printf("日");
	    printf("%d  ",TimeData.hour);
	    printf("时");
	    printf("%d  ",TimeData.minute);
	    printf("分");
	    printf("%d  ",TimeData.second);
	    printf("秒");
	    printf("星期");
	    printf("%d  ",TimeData.week);
		sprintf(realTime,"%d  ",TimeData.year);
		OLED_ShowString(8,0,realTime,16,1);
		OLED_ShowChinese(40,0,9,16,1);//年
		sprintf(realTime,"%d  ",TimeData.month);
		OLED_ShowString(56,0,realTime,16,1);
		OLED_ShowChinese(72,0,10,16,1);//月
		sprintf(realTime,"%d  ",TimeData.day);
		OLED_ShowString(88,0,realTime,16,1);
		OLED_ShowChinese(104,0,11,16,1);//日
		sprintf(realTime,"%d  ",TimeData.hour);
		OLED_ShowString(56,16,realTime,16,1);//时
		OLED_ShowString(72,16,"-",16,1);
		sprintf(realTime,"%d  ",TimeData.minute);
		OLED_ShowString(80,16,realTime,16,1);//分
		OLED_ShowString(96,16,"-",16,1);
		sprintf(realTime,"%d  ",TimeData.second);
		OLED_ShowString(104,16,realTime,16,1); //秒
		OLED_ShowChinese(0,16,0,16,1);//星期
		OLED_ShowChinese(16,16,1,16,1);
	
		switch(TimeData.week)
		{
			case 1:
			{
				OLED_ShowChinese(32,16,2,16,1);
			}break;
			case 2:
			{
				OLED_ShowChinese(32,16,3,16,1);
			}break;
			case 3:
			{
				OLED_ShowChinese(32,16,4,16,1);
			}break;
			case 4:
			{
				OLED_ShowChinese(32,16,5,16,1);
			}break;
			case 5:
			{
				OLED_ShowChinese(32,16,6,16,1);
			}break;
			case 6:
			{
				OLED_ShowChinese(32,16,7,16,1);
			}break;
			case 7:
			{
				OLED_ShowChinese(32,16,8,16,1);
			}
		
		}
		OLED_Refresh();
	}
}

读取实时时间数据,初始化串口和屏幕,把时间数据打印到串口上以及显示到OLED上。

结果

串口打印时间:
在这里插入图片描述
OLED显示时间:

在这里插入图片描述

总结

以上是基于STM32驱动DS1302时钟模块的实验代码。在这个代码中,主要实现了DS1302模块的初始化,读取时间和日期以及星期设置显示,并给出了相应的函数实现。在实际使用中大家可以添加一些其他的功能,比如桌面电子时钟,定时闹铃(报警)等。

猜你喜欢

转载自blog.csdn.net/qq_42250136/article/details/146377324
今日推荐