DS1307 RTC模块使用
创始人
2025-05-31 18:09:37

主要特性

DS1307是Maxim的串行、I2C实时时钟芯片。主要特性有:

  • 工作电压:主电源电压4.5~5.5V,电池电压2.0~3.5V

  • 功耗:电池供电、备份模式时<500nA

  • 接口:I2C,最大速率100kbps

  • 可编程方波输出

  • 电源自动切换、失效检测

  • 内置56字节大小、支持电池备份的RAM

  • 封装:8-Pin SO/PDIP

管脚定义

  • X1、X2: 接32.768kHz晶体,要求晶体负载电容12.5pF

  • Vcc:主电源,范围4.5~5.5V。当需要对DS1307读写时,需要接Vcc。

  • VBAT:接电池,范围2.0~3.5V。

  • GND:地

  • SDA、SCL:I2C接口数据线、时钟线。

  • SQW/OUT:方波输出脚、通过写寄存器来使能。

注意事项

  • DS1307的工作电压为4.5V-5.5V供电。

  • I2C总线控制DS1307,用GPIO模拟I2C时序即可。

  • 时间配置:直接把时间值写入0x00~0x06的时间寄存器。

  • 时间读取:直接读取0x00~0x06的时间寄存器即可。

  • 读取时间时发现未走时可能是00h 地址的寄存器第7 位为1,此位为1则芯片未开始工作,即时钟未走时,记得首次上电时把该位清零。

  • 首次上电设置时间后不必每次上电都再次初始化一下时间,停电后有备用电池,此时不必重写时间单元。

#include "global.h"
#include "drv_ds1307.h"#define I2C_CLK_PORT        GPIOB
#define I2C_CLK_PIN         GPIO_PIN_4#define I2C_SDA_PORT        GPIOB
#define I2C_SDA_PIN         GPIO_PIN_5#define SCL_High()        GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW) 
#define SCL_Low()         GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_LOW_SLOW)  
#define SDA_High()        GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW) 
#define SDA_Low()         GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_LOW_SLOW) 
#define SDAM()           (GPIO_ReadInputData(I2C_SDA_PORT) & 0x20) ?1:0
#define SET_SCL_OUT()    GPIO_Init(I2C_CLK_PORT, I2C_CLK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SET_SDA_OUT()    GPIO_Init(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define SET_SDA_IN()     GPIO_Init(GPIOA, GPIO_PIN_0, GPIO_MODE_IN_PU_NO_IT)extern uint8_t Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData);
extern uint8_t Ds1307_ReadByte(uint8_t ReadAddr);
extern void Ds1307_WriteData();
extern void Ds1307_ReadData();
extern void Init_Timer();
extern void Write_Time();uint8_t g_u8ReadData[8];/*******************************************************************************
//  Function:     I2C_Int
//  Description: 模拟I2C 与ds1307端口初始化
//  Param:        
//  Return:       
*******************************************************************************/
static void I2C_Int(void)
{SET_SDA_OUT();  SET_SCL_OUT();
}/*******************************************************************************
//  Function:     Delay_5us
//  Description:  微妙级延时函数   延时时间约为16us
//  Param:        
//  Return:       fcpu 16MHz 时
*******************************************************************************/
static void Delay_5us(void)
{uint8_t i;                 for (i=5; i>0; i--);
}/*******************************************************************************
//  Function:     I2C_Start
//  Description:  I2C 开始传输信号  当SCL 为高时  SDA由高变低
//  Param:        
//  Return:      
*******************************************************************************/
static void I2C_Start(void)
{// SDA 1->0 while SCL HighSDA_High();                   SCL_High();                    Delay_5us(); SDA_Low();                   Delay_5us(); SCL_Low();                    
}/*******************************************************************************
//  Function:     I2C_Stop
//  Description:  I2C 停止传输信号  当SCL 为高时  SDA由低变高
//  Param:        
//  Return:      
*******************************************************************************/
static void I2C_Stop(void)
{// SDA 0->1 while SCL HighSDA_Low();                   SCL_High();                   Delay_5us();     SDA_High();                   Delay_5us();               
}/*******************************************************************************
//  Function:     I2C_SendACK
//  Description:  主机向从机发送应答信号
//  Param:   应答信号 1:表示SDA高电平(无应答) 0:SDA低电平(有应答)
//  Return:      
*******************************************************************************/
static void I2C_SendACK(uint8_t ack)
{if(ack == 0){SDA_Low(); }  else{SDA_High(); }SCL_High();                   Delay_5us();  SCL_Low();                    Delay_5us();     
}/*******************************************************************************
//  Function:     I2C_SendByte
//  Description:  模拟I2C通信 发送8位数据
//  Param:        发送的8为数据值
//  Return:       返回应答信号  0表示有应答  1表示无应答
*******************************************************************************/
static uint8_t I2C_SendByte(uint8_t SendByte)
{static uint8_t i,RevAck;SDA_Low();for (i= 0 ; i< 8; i++)         {SCL_Low();    if (SendByte & 0x80)             // write data{SDA_High();}else   {SDA_Low();}Delay_5us();SendByte <<=  1;SCL_High();                Delay_5us();     } SCL_Low();   SDA_High();Delay_5us();  SET_SDA_IN();SCL_High();    asm("nop");asm("nop");  RevAck = (uint8_t)SDAM();Delay_5us();   SCL_Low();   SET_SDA_OUT();Delay_5us();  return RevAck;
}/*******************************************************************************
//  Function:     I2C_RecvByte
//  Description:  模拟I2C通信 从从机读取8位数据
//  Param:        
//  Return:       返回读取的8为数据值
*******************************************************************************/
static uint8_t I2C_RecvByte()
{uint8_t i;uint8_t RecvData = 0;SDA_High();     // latch the Data port befor readingSET_SDA_IN();for (i=0; i<8; i++)         { RecvData <<= 1;SCL_High(); asm("nop");asm("nop");if (SDAM()){RecvData |= 0x01;}else{RecvData &= 0xfe;}Delay_5us(); SCL_Low();                Delay_5us();  }SET_SDA_OUT();return RecvData;
}/*******************************************************************************
//  Function:     Ds1307_WriteByte
//  Description:  模拟I2C通信 写入1字节数据到指定地址
//  Param:        WriteAddr:待写入数据  WriteData;写入的地址
//  Return:       1: 成功写入  0: 写入出错
*******************************************************************************/
uint8_t Ds1307_WriteByte(uint8_t WriteAddr,uint8_t WriteData)
{I2C_Start();            if(I2C_SendByte(0xD0))    // Device Addr + Write (operation) {return 0; }if(I2C_SendByte(WriteAddr)){return 0;}if(I2C_SendByte(WriteData)){return 0; }I2C_Stop();   return 1;
}/*******************************************************************************
//  Function:     Ds1307_ReadByte
//  Description:  模拟I2C通信 从指定地址读取1字节数据
//  Param:        ReadAddr:读取的地址
//  Return:       RevData:读取的8位数据
*******************************************************************************/
uint8_t Ds1307_ReadByte(uint8_t ReadAddr)
{uint8_t RevData;I2C_Start();            I2C_SendByte(0xD0);     // Device Addr + Write (operation)   I2C_SendByte(ReadAddr); I2C_Start();    I2C_SendByte(0xD1);     // Device Addr + Write (operation)   RevData = I2C_RecvByte();    I2C_SendACK(1);I2C_Stop();   return RevData;
}/*******************************************************************************
//  Function:     Ds1307_WriteData
//  Description:  模拟I2C通信 写入8字节数据 从0x00~0x07
//  Param:        pWriteData: 指针指向待写入的数组的地址
//  Return:      
*******************************************************************************/
void Ds1307_WriteData()
{uint8_t i;uint8_t *pWriteData;pWriteData = (uint8_t *)&ICTimerBuf;I2C_Start();            I2C_SendByte(0xD0);     // Device Addr + Write (operation) I2C_SendByte(0x00); for(i=0; i<8; i++){I2C_SendByte(*pWriteData++); }I2C_Stop();             
}/*******************************************************************************
//  Function:     Ds1307_ReadData
//  Description:  模拟I2C通信 读取8字节数据 从0x00~0x07
//  Param:        pReadData: 指针指向保存数据的数组
//  Return:      
*******************************************************************************/
void Ds1307_ReadData()
{uint8_t i;uint8_t *pReadData;pReadData = (uint8_t *)&ICTimerBuf;I2C_Start();            I2C_SendByte(0xD0);     // Device Addr + Write (operation)   I2C_SendByte(0x00); I2C_Start();    I2C_SendByte(0xD1);     // Device Addr + Write (operation)   for(i=0; i<7; i++){// *pReadData++ = I2C_RecvByte();  *pReadData = I2C_RecvByte();pReadData++;if(i < 6)I2C_SendACK(0);    //DIO低电平 表示ACK 应答else I2C_SendACK(1);}I2C_Stop();   
}/*******************************************************************************
//  Function:     Init_Timer
//  Description:  上电初始化时钟以及读时钟
//  Param:       
//  Return:      判断0x00 地址bit7 是否为1  为1表示时钟芯片掉电
*******************************************************************************/
void Init_Timer()
{I2C_Int();Ds1307_ReadData();if(ICTimerBuf.TimerSec & 0x80){Ds1307_ReadData();if(ICTimerBuf.TimerSec & 0x80){ICTimerBuf.TimerSec =0x00;ICTimerBuf.TimerMin =0x00;ICTimerBuf.TimerHour =0x12;ICTimerBuf.TimerWeek =0x02;ICTimerBuf.TimerDay =0x15;ICTimerBuf.TimerMonth =0x04;ICTimerBuf.TimerYear =0x14;Ds1307_WriteData();}}ICTimer.TimerSec =(ICTimerBuf.TimerSec/16) * 10 +  (ICTimerBuf.TimerSec%16);ICTimer.TimerMin =(ICTimerBuf.TimerMin/16) * 10 +  (ICTimerBuf.TimerMin%16);ICTimer.TimerHour =((ICTimerBuf.TimerHour&0x1f)/16) * 10 +  ((ICTimerBuf.TimerHour&0x1f)%16);ICTimer.TimerWeek =(ICTimerBuf.TimerWeek/16) * 10 +  (ICTimerBuf.TimerWeek%16);ICTimer.TimerDay =(ICTimerBuf.TimerDay/16) * 10 +  (ICTimerBuf.TimerDay%16);ICTimer.TimerMonth =(ICTimerBuf.TimerMonth/16) * 10 +  (ICTimerBuf.TimerMonth%16);ICTimer.TimerYear =(ICTimerBuf.TimerYear/16) * 10 +  (ICTimerBuf.TimerYear%16);//更新系统时间参数g_u8TimeSettingHourValue = ICTimer.TimerHour;g_u8TimeSettingMinutesValue = ICTimer.TimerMin;g_u8TimeSettingAmPmValue = (ICTimerBuf.TimerHour &0x20)?1:0;
}/*******************************************************************************
//  Function:     Write_Time
//  Description:  如果设置了时钟则写入时钟
//  Param:       
//  Return:     
*******************************************************************************/
void Write_Time()
{if(g_u8TimeChangeFlag)    //如果设置了时钟{g_u8TimeChangeFlag = 0;ICTimerBuf.TimerSec = (ICTimer.TimerSec/10)*16 + (ICTimer.TimerSec%10);ICTimerBuf.TimerMin = (ICTimer.TimerMin/10)*16 + (ICTimer.TimerMin%10);ICTimerBuf.TimerHour = (ICTimer.TimerHour/10)*16 + (ICTimer.TimerHour%10);ICTimerBuf.TimerWeek = (ICTimer.TimerWeek/10)*16 + (ICTimer.TimerWeek%10);ICTimerBuf.TimerDay = (ICTimer.TimerDay/10)*16 + (ICTimer.TimerDay%10);ICTimerBuf.TimerMonth = (ICTimer.TimerMonth/10)*16 + (ICTimer.TimerMonth%10);ICTimerBuf.TimerYear = (ICTimer.TimerYear/10)*16 + (ICTimer.TimerYear%10);//转换为12时制时间if(g_u8TimeSettingAmPmValue %2)  //为1 表示 pM{ICTimerBuf.TimerHour |= 0x60;  }else  //为0表示AM{ICTimerBuf.TimerHour |= 0x40;  }//转换好之后把时间写入芯片Ds1307_WriteData();}
}
/*
*********************************************************************************************************
*    函 数 名: uint8_t DS1307_Read(uint8_t address)
*    功能说明: 向DS1307寄存器读取数据
*    形    参:寄存器地址
*    返 回 值: 读出的数据
*********************************************************************************************************
*/
uint8_t DS1307_Read(uint8_t address)
{uint8_t dat;    i2c_Start();i2c_SendByte(0xD0);//发送设备地址,写指令i2c_WaitAck();i2c_SendByte(address);//发送寄存器地址i2c_WaitAck();i2c_Stop();i2c_Start();//重新启动IIC总线i2c_SendByte(0xD1);    //发送设备地址,读指令i2c_WaitAck();dat=i2c_ReadByte(); //读一个字节数据i2c_NAck();    i2c_Stop();return dat;
}/*
*********************************************************************************************************
*    函 数 名: DS1307_Wirte(uint8_t address , uint8_t dat)
*    功能说明: 向DS1307寄存器写数据
*    形    参:address:寄存器地址,dat:要写入的数据
*    返 回 值: 无
*********************************************************************************************************
*/
void DS1307_Wirte(uint8_t address , uint8_t dat)
{ i2c_Start();i2c_SendByte(0xD0);//发送设备地址,写指令i2c_WaitAck();i2c_SendByte(address);//发送寄存器地址i2c_WaitAck();i2c_SendByte(dat);//写一个字节数据i2c_WaitAck();i2c_Stop();    
}/*
*********************************************************************************************************
*    函 数 名: void DS1307_Init_Time(void)
*    功能说明: 第一次上电时,需要初始化时间,初始化一次后就不必重复初始化
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
void DS1307_Init_Time(void)
{if(DS1307_Read(FLAG_ADDR)!=FLAG_VAL)//如果未初始化,执行初始化时间{DS1307_Set_Time(2023,2,16,19,02,00,4);//2023年2月16日 17:50:00 星期四printf("时间初始化完成,flag=%d\r\n",DS1307_Read(FLAG_ADDR));}    else{printf("时间已初始化过,flag=%d\r\n",DS1307_Read(FLAG_ADDR));}
}
//时间初始化设置
void DS1307_Set_Time(uint16_t year,uint8_t mon,uint8_t day,uint8_t hour,uint8_t min,uint8_t sec,uint8_t week)
{year-=2000;//年默认2000年开始if(year > 100) year = 0;//十进制转为BCD码year = ((year /10) << 4) + year %10;mon  = ((mon  /10) << 4) + mon  %10;day  = ((day  /10) << 4) + day  %10;week = ((week /10) << 4) + week  %10;hour = ((hour /10) << 4) + hour %10;min  = ((min  /10) << 4) + min  %10;sec  = ((sec  /10) << 4) + sec  %10;//写入寄存器,同时标记一个地址DS1307_Wirte(FLAG_ADDR,FLAG_VAL);   //写入已经设置时间标志        DS1307_Wirte(0x00,sec);    //设置秒DS1307_Wirte(0x01,min);    //设置分DS1307_Wirte(0x02,hour);   //设置时DS1307_Wirte(0x03,week);   //设置周DS1307_Wirte(0x04,day);    //设置日DS1307_Wirte(0x05,mon);    //设置月    DS1307_Wirte(0x06,year);   //设置年        
}
//获取当前时间
void Get_Now_Time(void)
{uint8_t sec,min,hour,week,day,mon,year;uint8_t i;sec  = DS1307_Read(0x00);min  = DS1307_Read(0x01);hour = DS1307_Read(0x02);week = DS1307_Read(0x03);    day  = DS1307_Read(0x04);mon  = DS1307_Read(0x05);year = DS1307_Read(0x06);//BCD码转十进制date_time.sec  = (sec/16)*10 + sec%16;date_time.min  = (min/16)*10 + min%16;date_time.hour = (hour/16)*10 + hour%16;date_time.day  = (day/16)*10  + day%16;date_time.mon  = (mon/16)*10  + mon%16;date_time.year = (year/16)*10 + year%16 + 2000;date_time.week = (week/16)*10 + week%16;               
}

相关内容

热门资讯

头歌--第1关:Linux文件... 任务描述 假设系统中存在一个文件File,修改该文件的权限,根据实际需求...
【Spring从成神到升仙系列... 👏作者简介:大家好,我是爱敲代码的小黄,独...
梦见蜈蚣是什么意思,做梦梦见蜈... 梦见蜈蚣是什么意思目录梦见蜈蚣是什么意思做梦梦见蜈蚣什么意思梦见蜈蚣是什么意思,哪里有解释啊梦见蜈蚣...
小区车位比一般是多少,车库配比... 小区车位比一般是多少目录小区车位比一般是多少车库配比是什么小区总户数8200,总车位是1450个,配...
车锁上的lock什么意思,汽车... 车锁上的lock什么意思目录车锁上的lock什么意思汽车上lock是什么意思?车子上“lock标志”...
kirin710是什么处理器,... kirin710是什么处理器目录kirin710是什么处理器海思kirin710是高通多少?骁龙71...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
跟着文档制作cocos第一个游... 背景 近期打算学习一下cocos creator,想着开发自己的游戏,是...
乌干达是什么梗,网络语乌干达什... 乌干达是什么梗目录乌干达是什么梗网络语乌干达什么意思?乌干达是什么梗乌干达是什么梗乌干达是什么梗 ...
车载电子狗怎么用,怎样使用电子... 车载电子狗怎么用目录车载电子狗怎么用怎样使用电子狗怎么使用电子狗求简答车载电子狗怎么使用车载电子狗怎...
梦见偷东西是什么意思,梦见自己... 梦见偷东西是什么意思目录梦见偷东西是什么意思梦见自己偷东西是什么意思?做梦梦见自己偷东西好不好梦见偷...
黄金瞳到底是什么,黄金瞳电视剧... 黄金瞳到底是什么目录黄金瞳到底是什么黄金瞳电视剧什么时候上映?《黄金瞳》的结局是什么?电视剧《黄金瞳...
前端-session、jwt 目录:   (1)session (2&#x...
企业即时通讯怎样为企业实现移动... 对于企业来说,在办公过程中少不了工作人员相互传递信息和数据传输,企业内部...
骑行选择什么自行车 极速百科网... 骑行选择什么自行车目录骑行选择什么自行车骑行选择什么自行车 1. 山地自行车:适合崎岖不平的路...
蓝色都有哪几种,蓝色都有什么颜... 蓝色都有哪几种目录蓝色都有哪几种蓝色都有什么颜色的蓝图片,蓝色都有什么颜色的蓝二年级蓝色有哪些种类蓝...
如何自学游泳要安全的,初学游泳... 如何自学游泳要安全的目录如何自学游泳要安全的初学游泳的人需要准备哪些东西,注意哪些事项?如何自学游泳...
一年级家长的话怎么写评语,一年... 一年级家长的话怎么写评语目录一年级家长的话怎么写评语一年级学生评价手册家长寄语怎么写一年级最佳家长评...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
docker 镜像管理 查看本地镜像 docker images 可以查看本地下载的镜像 docker images [O...
k8s-1.22.15部署ng... 1.介绍 在前面文章中已经提到,Service对集群之外暴露服务的主要方式有两种&#x...
革命烈士寄语怎么写,清明节缅怀... 革命烈士寄语怎么写目录革命烈士寄语怎么写清明节缅怀先烈的寄语有哪些呢?革命烈士寄语怎么写 革命...
5万元以下新车推荐,5万以下买... 本篇文章极速百科给大家谈谈5万元以下新车推荐,5万以下买什么车好,以及5万以下的新车哪款最好对应的知...
真皮沙发翻新一般多少钱?(真皮... 本篇文章极速百科给大家谈谈真皮沙发翻新一般多少钱?,以及真皮沙发翻新一般多少钱一个对应的知识点,希望...
磨皮什么意思(磨皮是啥?) 磨... 本篇文章极速百科给大家谈谈磨皮什么意思,以及磨皮是啥?对应的知识点,希望对各位有所帮助,不要忘了收藏...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
从NVIDIA GTC大会,看... 从NVIDIA GTC 2023这场全球行业盛宴,我们可以解读出AI算力行业的哪些重要...
请问什么是童子,什么是童子 极... 请问什么是童子目录请问什么是童子什么是童子古代 童子是什么意思童子是什么意思?请问什么是童子 ...
中招考试考哪些科目,中招考试考... 中招考试考哪些科目目录中招考试考哪些科目中招考试考几门科目一共多少分?中考有哪些科目中考考几科,都什...
做电商如何做,电商怎样做才能赚... 做电商如何做目录做电商如何做电商怎样做才能赚钱?做的好的电商朋友可以教教我怎么做吗新手小白怎么做跨境...