一、简介
DS1339串行实时时钟(RTC)是低功耗的时钟/日历芯片,具有两个可编程日历闹钟与一路可编程方波输出。地址与数据通过I²C总线串行传送。时钟/日历可以提供秒、分、时、日、月、年信息。对于少于31天的月份,到每月的最后一天会自动进行调节,包括闰年修正。该时钟可以通过AM/PM指示器工作在24小时模式或12小时模式。DS1339具有一个内部电源感应电路,可以检测到电源失效,并自动转换到备用电源。
二、特性
- 实时时钟(RTC)记录秒、分、时、星期、日、月、年信息,具有有效至2100年的闰年补偿
- 内置晶振(DS1339C),采用表面贴封装
- I²C串行接口
- 2个日历闹钟
- 可编程方波输出
- 振荡器停止标志
- 自动电源失效检测与转换电路
- 提供涓流充电
三、笔记
1、P17-特性:如果之前有发送命令地址,则读数据命令,会从上个地址顺延,并读取数据。
直到发送了新的命令地址。
2、P17-器件读写操作流程
说明:
☆ 时间寄存器的B6选择12或24小时模式,1=12小时模式,0=24小时模式;
☆ 12小时模式时,AM/PM位=1是PM,0=AM;
☆ 24小时模式时,小时寄存器的B5是10小时位(20到23时);
☆ 当12/24模式改变时,所有的小时值(包括报警)都必须重新输入;
☆ 当从99年到00年时,就触发月寄存器的B7(世纪);
☆ 星期寄存器在午夜递增,和星期对应的值是可以自定义的,但必须是顺序的(如1对应星期天,则2就对应星期一,等等);
☆ 控制寄存器的INTCN位使能报警;
☆ 控制寄存器0EH
EOSC:晶振使能0=启动晶振,1=停止晶振,缺省=0;
BBSQI:1=当没有VCC使用VBACKUP时输出方波或中断,0=当VCC低于VPF时SQW/INT脚变成高阻态。缺省是0;
RS2:RS1:控制方波输出频率,如下表所示,缺省是11;
四、示例代码
#include "ds1339.h"
/*************笔记****[DS1339数据手册.pdf]************
*******************************************************/
/*声明内部函数*/
uint8_t ConvertDataToSet(const T_DS1339TIME *time, uint8_t regType);
void ConvertDataToGet(uint8_t rData, T_DS1339TIME *time, uint8_t regType);
/*********************************************
函数名:DS1339Init
功 能:初始化器件的IIC引脚
形 参:PIN --IIC信息结构体
**********************************************/
void DS1339Init(const IIC_PIN *PIN)
{
IIC_Init(PIN);
}
/******************************
函数名:DS1339GetTime
功 能:设置器件时间
形 参:PIN --IIC信息结构体
time --存放器件时间的信息结构体
返回值:
备 注:特性,器件寄存器地址,每次写入1byte,就会自动递增到下一个地址。
*******************************/
IIC_STATUS DS1339SetTime(const IIC_PIN *PIN, const T_DS1339TIME *time)
{
IIC_STATUS status;
uint8_t i, sendData;
osDelay(100);
IIC_Start(PIN);
IIC_WriteByte(PIN, PIN->ADDR);
status = IIC_Wait_ACK(PIN);
IIC_WriteByte(PIN, REGADDR_SECONDS);
status |= IIC_Wait_ACK(PIN);
for(i = 0; i < 7; i++)
{
sendData = ConvertDataToSet(time, REGADDR_SECONDS + i); //时间格式转换
IIC_WriteByte(PIN, sendData);
status |= IIC_Wait_ACK(PIN);
}
IIC_Stop(PIN);
if(status)
return(IIC_WRITE_ERR);
else
return(IIC_OK);
}
/******************************
函数名:DS1339GetTime
功 能:从器件读取时间
形 参:PIN --IIC信息结构体
time --存放器件时间的信息结构体
*******************************/
IIC_STATUS DS1339GetTime(const IIC_PIN *PIN, T_DS1339TIME *time)
{
T_DS1339TIME rTime;
uint8_t i, rData[7];
IIC_STATUS status;
IIC_Start(PIN);
IIC_WriteByte(PIN, PIN->ADDR);
status = IIC_Wait_ACK(PIN);
IIC_WriteByte(PIN, REGADDR_SECONDS);
status |= IIC_Wait_ACK(PIN);
IIC_Start(PIN);
IIC_WriteByte(PIN, PIN->ADDR | 0x01);
status |= IIC_Wait_ACK(PIN);
for(i = 0; i < 7; i++) //从器件寄存器中按顺序读取 秒,分,时,天(0-7),日,月,年
{
if(i != 0 )
IIC_ACK(PIN);
IIC_ReadByte(PIN, &rData[i]);
}
IIC_NACK(PIN);
IIC_Stop(PIN);
/*时间转换*/
for(i = 0; i < 7; i++)
{
ConvertDataToGet(rData[i], &rTime, REGADDR_SECONDS + i);
}
if(status)
{
return (IIC_READ_ERR);
}
else
{
*time = rTime;
return (IIC_OK);
}
}
/******************************************************************
函数名:ConvertDataToSet
功 能:设置器件时间,因为器件寄存器对时间格式有要求,
所以需要对时间进行转换,具体看手册。
形 参:
time --向器件设置时间的信息结构体
regType --时间类型
返回值:
备 注:DS1339数据手册.pdf --10页--寄存器说明
*******************************************************************/
uint8_t ConvertDataToSet(const T_DS1339TIME *time, uint8_t regType)
{
uint8_t sendData = 0;
switch(regType)
{
case REGADDR_SECONDS:
if(time->second > 10)
{
sendData = ((time->second / 10) << 4) & 0x7F;
sendData |= time->second % 10;
}
else
{
sendData = time->second;
}
break;
case REGADDR_MINUTES:
if(time->minute > 10)
{
sendData = ((time->minute / 10) << 4) & 0x7F;
sendData |= time->minute % 10;
}
else
{
sendData = time->minute;
}
break;
case REGADDR_HOURS:
if(time->hour > 10)
{
sendData = ((time->hour / 10) << 4) & 0x1F;
sendData |= time->hour % 10;
}
else
{
sendData = time->hour;
}
break;
case REGADDR_DAY:
sendData = time->weekday & 0x0E;
break;
case REGADDR_DATA:
if(time->day > 10)
{
sendData = ((time->day / 10) << 4) & 0x3F;
sendData |= time->day % 10;
}
else
{
sendData = time->day;
}
break;
case REGADDR_MONTH_CENTURY:
if(time->month > 10)
{
sendData = ((time->month / 10) << 4) & 0x1F;
sendData |= time->month % 10;
}
else
{
sendData = time->month;
}
break;
case REGADDR_YEAR:
if(time->year > 10)
{
sendData = ((time->year / 10) << 4) & 0xF0;
sendData |= time->year % 10;
}
else
{
sendData = time->year;
}
break;
default:
;
}
return sendData;
}
/******************************************************************
函数名:ConvertDataToGet
功 能:从器件获取时间的需要转换,因为器件寄存器对时间格式有要求,
所以需要对时间进行转换,具体看手册。
形 参:
time --存放器件时间的信息结构体
regType --时间类型
返回值:
备 注:DS1339数据手册.pdf --10页--寄存器说明
*******************************************************************/
void ConvertDataToGet(uint8_t rData, T_DS1339TIME *time, uint8_t regType)
{
switch(regType)
{
case REGADDR_SECONDS:
time->second = (rData >> 4 & 0x07) * 10 + (rData & 0x0F);
break;
case REGADDR_MINUTES:
time->minute = (rData >> 4 & 0x07) * 10 + (rData & 0x0F);
break;
case REGADDR_HOURS:
time->hour = (rData >> 4 & 0x01) * 10 + (rData & 0x0F);
break;
case REGADDR_DAY:
time->weekday = rData & 0x07;
break;
case REGADDR_DATA:
time->day = (rData >> 4 & 0x03) * 10 + (rData & 0x0F);
break;
case REGADDR_MONTH_CENTURY:
time->month = (rData >> 4 & 0x01) * 10 + (rData & 0x0F);
break;
case REGADDR_YEAR:
time->year = (rData >> 4 & 0x0F) * 10 + (rData & 0x0F);
break;
default:
;
}
}
#ifndef _DS1339_HEAD_
#define _DS1339_HEAD_
#include "stdio.h"
#include "stdint.h"
#include "stdlib.h"
#include "cmsis_os.h"
#include "hal_iic.h"
/*************笔记****************
1、S1339数据手册.pdf --10页--寄存器说明
***********************************/
/*需要首次初始化时,配置以下寄存器*/
#define REGADDR_SECONDS 0x00 //秒 寄存器
#define REGADDR_MINUTES 0x01 //分 寄存器
#define REGADDR_HOURS 0x02 //时 寄存器
#define REGADDR_DAY 0x03 //周日 寄存器
#define REGADDR_DATA 0x04 //日 寄存器
#define REGADDR_MONTH_CENTURY 0x05 //月 寄存器
#define REGADDR_YEAR 0x06 //年 寄存器
/*需要设置闹钟,可以配置以下寄存器,否则默认即可*/
#define REGADDR_ALARM1SECONDS 0x07 //闹钟1-秒 寄存器
#define REGADDR_ALARM1MINUTES 0x08 //闹钟1-分 寄存器
#define REGADDR_ALARM1HOURS 0x09 //闹钟1-时 寄存器
#define REGADDR_ALARM1DAY_ALARM1DATE 0x0A //闹钟1-周日-日 寄存器
#define REGADDR_ALARM2MINUTES 0x0B //闹钟2-分 寄存器
#define REGADDR_ALARM2HOURS 0x0C //闹钟2-时 寄存器
#define REGADDR_ALARM2DAY_ALARM2DATE 0x0D //闹钟2-周日-日 寄存器
/*以下寄存器默认即可*/
#define REGADDR_CONTROL 0x0E //控制寄存器,用于设置晶振频率
#define REGADDR_STATUS 0x0F //状态
#define REGADDR_TRICKLECHARGER 0x10
/*DS1339时间信息结构体*/
typedef struct //24小时制
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint8_t year; //00-99
} T_DS1339TIME;
void DS1339Init(const IIC_PIN *PIN);
IIC_STATUS DS1339SetTime(const IIC_PIN *PIN, const T_DS1339TIME *time);
IIC_STATUS DS1339GetTime(const IIC_PIN *PIN, T_DS1339TIME *time);
#endif