一、模块介绍
DS1302时钟模块是一款由美国DALLAS公司生产的高性能、低功耗的实时时钟芯片。它可以对年、月、日、时、分、秒进行计时,并具有闰年补偿功能。该芯片内部集成了一个31字的RAM寄存组,用于临时存放数据。其接口简单,与TTL兼容。 以下是DS1302时钟模块的主要特点:
1. 实时时钟:DS1302可以准确地计时年、月、日、时、分、秒,适用于需要精确时间控制的场合。
2. 闰年补偿:DS1302能够自动进行闰年补偿,确保日历数据的准确性。
3. 低功耗:DS1302在正常工作状态下功耗较低,有利于延长系统续航时间。
4. 涓流充电:DS1302具备涓流充电功能,可以对备用电源进行充电,提高了系统的可靠性。
5. 3线接口:DS1302采用简单的3线接口与微处理器通讯,便于集成到各种系统中。
6. 兼容性:DS1302与DS1202兼容,可以替代DS1202在相关应用中使用。
7. 宽电压范围:DS1302的工作电压范围为2.5V至5.5V,适应不同电源环境。
DS1302时钟模块在许多应用领域都有广泛的应用,如嵌入式系统、智能家居、工业自动化等。通过与单片机等微处理器配合使用,可以实现实时时间显示、数据记录等功能。
二、资料获取
关注微信公众号--星之援工作室 发送关键字(DS1302)
➡️➡️
效果展示
接线规则(可在ds1302.h中自行修改)
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
三、代码编写
main
用于显示处理,当时钟模块的秒更新之后就会通过串口输出
/*--------------------------------------------------------*
* *
* 星之援网络科技工作室学习资料v1.0 *
* 时间:2022.7.14 *
* 程序介绍:DS1302实验 *
* 实现效果:串口输出系统时间 *
* *
*--------------------------------------------------------*
*/
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "ds1302.h"
int main(void)
{
DS1302_Time_t time = {0};
char str[50];
u8 sec=0;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
// LED 端口初始化
LED_GPIO_Config();
// KEY 初始化
Key_GPIO_Config();
// 串口初始化
uart_init(115200);
//初始化ds1302端口
DS1302_Init();
printf("init okn");
while(1)
{
DS1302_GetTime(&time); //读取此时时刻
if(sec==time.second)//判断秒钟数是否有更新
{
delay_ms(5);//没有更新便延时5ms
}
else
{
sec=time.second;//秒钟数有更新,则将变量sec更新
sprintf(str,"Data: %d-%d-%d Time: %d:%d:%d ",time.year,time.month,time.day,
time.hour,time.minute,time.second);
printf("%sn",str);
}
}
}
ds1302.c
驱动代码
#include "ds1302.h"
#include "delay.h"
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
//DS1302地址定义
#define DS1302_SEC_ADDR 0x80 //秒数据地址
#define DS1302_MIN_ADDR 0x82 //分数据地址
#define DS1302_HOUR_ADDR 0x84 //时数据地址
#define DS1302_DAY_ADDR 0x86 //日数据地址
#define DS1302_MONTH_ADDR 0x88 //月数据地址
#define DS1302_WEEK_ADDR 0x8a //星期数据地址
#define DS1302_YEAR_ADDR 0x8c //年数据地址
#define DS1302_CONTROL_ADDR 0x8e //控制数据地址
#define DS1302_CHARGER_ADDR 0x90 //充电功能地址
#define DS1302_CLKBURST_ADDR 0xbe
//初始时间定义
static u8 time_buf[8] = {0x20,0x19,0x04,0x12,0x15,0x07,0x00,0x06};//初始时间2019年4月12号15点07分00秒 星期五
u8 sec_buf=0; //秒缓存
u8 sec_flag=0; //秒标志位
void DS1302_Init()//CE,SCLK端口初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(CE_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = CE_GPIO_PIN; //PC.11 CE
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(CE_GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.11
GPIO_ResetBits(CE_GPIO_PORT,CE_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = SCLK__GPIO_PIN; //PC.12 SCLK
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(SCLK__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.12
GPIO_ResetBits(SCLK__GPIO_PORT,SCLK__GPIO_PIN);
}
//配置双向I/O端口为输出态
static void ds1032_DATAOUT_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DATA_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DATA__GPIO_PIN; //PC.10 DATA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(DATA__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.10
GPIO_ResetBits(DATA__GPIO_PORT,DATA__GPIO_PIN);
}
//配置双向I/O端口为输入态
static void ds1032_DATAINPUT_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DATA_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DATA__GPIO_PIN; //PC.10 DATA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DATA__GPIO_PORT, &GPIO_InitStructure);//初始化GPIOC.10
}
//向DS1302写入一字节数据
void DS1302_WriteByte(u8 addr,u8 data)
{
u8 i;
DS1302_RST=0; //禁止数据传输 !!!这条很重要
DS1302_CLK=0; //确保写数据前SCLK为低电平
DS1302_RST=1; //启动DS1302总线
ds1032_DATAOUT_init();
addr=addr&0xFE; //最低位置零,寄存器0位为0时写,为1时读
for(i=0;i<8;i++) //写入目标地址:addr
{
if (addr&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //时钟上升沿写入数据
DS1302_CLK=0;
addr=addr>>1;
}
for (i=0;i<8;i++) //写入数据:data
{
if(data&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //时钟上升沿写入数据
DS1302_CLK=0;
data = data >> 1;
}
DS1302_CLK=1; // 将时钟电平置于高电平状态 ,处于已知状态
DS1302_RST=0; //停止DS1302总线
}
//从DS1302读出一字节数据
u8 DS1302_ReadByte(u8 addr)
{
u8 i,temp;
DS1302_RST=0; //这条很重要
DS1302_CLK=0; //先将SCLK置低电平,确保写数居前SCLK被拉低
DS1302_RST=1; //启动DS1302总线
ds1032_DATAOUT_init();
//写入目标地址:addr
addr=addr|0x01; //最低位置高,寄存器0位为0时写,为1时读
for(i=0;i<8;i++)
{
if (addr&0x01) DS1302_OUT=1;
else DS1302_OUT=0;
DS1302_CLK=1; //写数据
DS1302_CLK=0;
addr = addr >> 1;
}
//从DS1302读出数据:temp
ds1032_DATAINPUT_init();
for(i=0;i<8;i++)
{
temp=temp>>1;
if (DS1302_IN) temp|=0x80;
else temp&=0x7F;
DS1302_CLK=1;
DS1302_CLK=0;
}
DS1302_CLK=1; //将时钟电平置于已知状态
DS1302_RST=0; //停止DS1302总线
return temp;
}
//向DS1302写入时钟数据,用于时间校准修改
void DS1302_WriteTime()
{
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x00); //关闭写保护
DS1302_WriteByte(DS1302_SEC_ADDR,0x80); //暂停时钟
//DS1302_WriteByte(DS1302_CHARGER_ADDR,0xa9); //涓流充电
DS1302_WriteByte(DS1302_YEAR_ADDR,time_buf[1]); //年
DS1302_WriteByte(DS1302_MONTH_ADDR,time_buf[2]); //月
DS1302_WriteByte(DS1302_DAY_ADDR,time_buf[3]); //日
DS1302_WriteByte(DS1302_HOUR_ADDR,time_buf[4]); //时
DS1302_WriteByte(DS1302_MIN_ADDR,time_buf[5]); //分
DS1302_WriteByte(DS1302_SEC_ADDR,time_buf[6]); //秒
DS1302_WriteByte(DS1302_WEEK_ADDR,time_buf[7]); //周
DS1302_WriteByte(DS1302_CHARGER_ADDR,0xA5);//打开充电功能 选择2K电阻充电方式
DS1302_WriteByte(DS1302_CONTROL_ADDR,0x80);//打开写保护
}
//从DS1302读出时钟数据
void DS1302_ReadTime(void)
{
time_buf[1]=DS1302_ReadByte(DS1302_YEAR_ADDR); //年
time_buf[2]=DS1302_ReadByte(DS1302_MONTH_ADDR); //月
time_buf[3]=DS1302_ReadByte(DS1302_DAY_ADDR); //日
time_buf[4]=DS1302_ReadByte(DS1302_HOUR_ADDR); //时
time_buf[5]=DS1302_ReadByte(DS1302_MIN_ADDR); //分
time_buf[6]=(DS1302_ReadByte(DS1302_SEC_ADDR))&0x7f; //秒,屏蔽秒的第7位,避免超出59
time_buf[7]=DS1302_ReadByte(DS1302_WEEK_ADDR); //周
}
//主函数
void DS1302_GetTime(DS1302_Time_t* time)
{
DS1302_ReadTime(); //读取时间
time->year=(time_buf[0]>>4)*1000+(time_buf[0]&0x0F)*100+(time_buf[1]>>4)*10+(time_buf[1]&0x0F); //计算年份
time->month=(time_buf[2]>>4)*10+(time_buf[2]&0x0F); //计算月份
time->day=(time_buf[3]>>4)*10+(time_buf[3]&0x0F); //计算日期
time->hour=(time_buf[4]>>4)*10+(time_buf[4]&0x0F); //计算小时
time->minute=(time_buf[5]>>4)*10+(time_buf[5]&0x0F); //计算分钟
time->second=(time_buf[6]>>4)*10+(time_buf[6]&0x0F); //计算秒钟
time->week=(time_buf[7]&0x0F); //计算星期
//printf("时间:%d-%d-%d %d:%d:%d %d n",TimeData.year,TimeData.month,TimeData.day,TimeData.hour,TimeData.minute,TimeData.second,TimeData.week);
}
ds1302.h
参数定义
#ifndef __ds1302_H
#define __ds1302_H
#include "sys.h"
/*
DS1302接口:
VCC -> 5.0/3.3
GND -> GND
GPIOB_14 ->DS1302_RST
GPIOB_13 ->DS1302_DAT
GPIOB_12 ->DS1302_CLK
*/
/* 定义LED连接的GPIO端口, 用户只需要修改下面的代码即可改变控制的LED引脚 */
#define CE_GPIO_PORT GPIOB /* GPIO端口 */
#define CE_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define CE_GPIO_PIN GPIO_Pin_14 /* 连接到SCL时钟线的GPIO */
#define SCLK__GPIO_PORT GPIOB /* GPIO端口 */
#define SCLK_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define SCLK__GPIO_PIN GPIO_Pin_12 /* 连接到SCL时钟线的GPIO */
#define DATA__GPIO_PORT GPIOB /* GPIO端口 */
#define DATA_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define DATA__GPIO_PIN GPIO_Pin_13 /* 连接到SCL时钟线的GPIO */
//DS1302引脚定义,可根据实际情况自行修改端口定义
//#define DS1302_OutPut_Mode() {GPIOB->CRL &= 0xF0FFFFFF;GPIOB->CRL |= 0x03000000;}//将 GPIOA 口的 PA6 引脚设置成推挽输出模式,并清空了其他引脚的配置
//#define DS1302_InPut_Mode() {GPIOB->CRL &= 0xF0FFFFFF;GPIOB->CRL |= 0x08000000;}//PA7 引脚既可以作为普通的 GPIO 输出口
#define DS1302_IN PBin(13)
#define DS1302_OUT PBout(13)
#define DS1302_RST PBout(14)
#define DS1302_CLK PBout(12)
typedef struct TIMEData
{
u16 year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 week;
}DS1302_Time_t;
//创建TIMEData结构体方便存储时间日期数据
void DS1302_Init(void);
void DS1302_WriteByte(u8 addr,u8 data);
u8 DS1302_ReadByte(u8 addr);
void DS1302_WriteTime(void);
void DS1302_ReadTime(void);
void DS1302_GetTime(DS1302_Time_t* time);
#endif
四、参考
基于STM32的DS1302时钟模块驱动程序https://blog.csdn.net/qq_43270506/article/details/104952746?ops_request_misc=&request_id=&biz_id=102&utm_term=stmDS1302&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-4-104952746.142%5Ev96%5Epc_search_result_base7&spm=1018.2226.3001.4187
STM32基于标准库工程驱动DS1302https://blog.csdn.net/weixin_42880082/article/details/129941871?ops_request_misc=&request_id=&biz_id=102&utm_term=stm%20DS1302&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~sobaiduweb~default-4-129941871.nonecase&spm=1018.2226.3001.4450
完整代码请关注公众号进行获取和咨询
联系方式 微信号:13648103287