实时时钟芯片DS1307的使用及驱动代码
DS1307实时时钟芯片的介绍及驱动代码,帮助初学者的使用
·
DS1307实时时钟芯片的介绍及驱动代码
目录
一、DS1307是什么?
DS1307是一款基于IIC总线接口的实时时钟芯片,可以独立于MCU工作,芯片具有备用电源自动切换功能,可以在主电源掉电或其他一些恶劣环境下保证系统时钟的准确。
二、DS1307的功能
- DS1307具有产生时、分、秒、日、月、年等功能,闰年可自动调整,日历和时钟数据以BCD码的方式存放在片内的寄存器上。
- 片内集成了56字节的具有掉电后电池保持的RAM数据存储器,可以用来保存一些关键数据,
- 芯片具有掉电检测和自动切换电池供电功能,当DS1307靠后备电池维持工作时,拒绝CPU对其的读出和写入操作。
三、DS1307的寄存器
DS1307片内有多个时间保存寄存器,单片机就是通过读取这些寄存器得到时间和日期相关的数据的,其中有8个寄存器专门用来存储时间信息,另外56个字节的RAM可以供用户自由使用。
- 时间和日历信息在时间保存寄存器上的存放是以BCD码的形式存放的,以分钟寄存器为例,分的十位存放寄存器的高四位,分的个位存放在寄存器的低四位。
- 日期和星期寄存器的值会在每天的午夜递增,我们需要在程序中指定星期与星期寄存器的对应关系,也就是说把星期寄存器值为1时定义为星期一,那么当读取的值为1时就应当是星期日。
- 寄存器0(地址00h)的第7位是时钟停止位CH。当这一位置1时,时间振荡器会被禁止,该位清零时,振荡器会使能。
- 芯片在第一次上电时,时间和日期会被复位成:01月01日00年、星期01、00时00分00秒,秒寄存器的CH位会被设定为1。我们在对时间值进行设定时,需将CH位清零以使能振荡器。
- DS1307可以运行在12小时模式或24小时模式。小时寄存器的bit6是定义12小时或24小时模式选择位。当该位置1时,时钟被定义为12小时模式,清零时为24小时模式。
- DS1307可以设定为12小时模式下,小时寄存器的bit5是AM/PM位,其值为0时表示AM,为1时表示PM;在24小时模式下bit5是20小时位(20-23)。
四、代码
1.读出数据
/*
*********************************************************************************************************
* 函 数 名: 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;
}
2.写入数据
/*
*********************************************************************************************************
* 函 数 名: 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();
}
3.时间初始化设置
/*
*********************************************************************************************************
* 函 数 名: 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); //设置年
}
4.获取当前时间
//获取当前时间
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;
}
五、注意事项
- DS1307的工作电压为4.5V-5.5V供电。
- I2C总线控制DS1307,用GPIO模拟I2C时序即可。
- 时间配置:直接把时间值写入0x00~0x06的时间寄存器。
- 时间读取:直接读取0x00~0x06的时间寄存器即可。
- 读取时间时发现未走时可能是00h 地址的寄存器第7 位为1,此位为1则芯片未开始工作,即时钟未走时,记得首次上电时把该位清零。
- 首次上电设置时间后不必每次上电都再次初始化一下时间,停电后有备用电池,此时不必重写时间单元。
总结
本文简单介绍了DS1307实时时钟芯片的使用,提供了DS1307的驱动程序代码,方便首次使用DS1307的初学者们学习和参考。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)