RX8025T是一款高精度实时时钟(RTC)芯片,以下是对其的详细介绍:
一、基本信息
- 生产厂家:瑞昱半导体公司(Realtek Semiconductor),也有说法认为是由爱普生(EPSON)生产,可能是基于爱普生广受追捧的RX-8025SA和RX-8025NB系列时钟芯片基础上推出的中国定制款。
- 类型:拥有I2C(也有说法为12C,但I2C更为常见)接口和温度补偿功能的新型实时时钟芯片。
二、主要特点
- 高精度与温度补偿:内置高稳定度的32.768KHz的DTCXO(数字温度补偿晶体振荡器),通过设置相应补偿的控制位,可以实现不同间隔的温度补偿功能,从而大大提高了时钟的精度。芯片可设置四种不同的时段进行温度补偿,默认设置是2S补偿。
- 低功耗:采用C-MOS工艺生产,具有极低的功能消耗,低电流功耗为0.8uA/3V(Typ.),可长期使用电池供电。
- 宽电压范围:接口电压范围为2.2V到5.5V,时间保持电压范围为1.8V到5.5V。
- 多功能:支持I2C总线的高速模式(400K);具有固定周期定时中断功能、时间更新中断功能;闰年自动调整功能(2000到2099年);可通过FOUT引脚输出一个32.768kHz频率的时钟信号,该功能可以通过FOE引脚控制;具有定时报警功能(可设定天、日期、小时、分钟)。
- 工作温度范围:根据不同版本有所不同,如RX8025T UB(工业级)的工作温度范围为-40℃到+85℃,而RX8025T UC(民用级或商业级)的工作温度范围为-30℃到+70℃。两者在保证精度上均为5ppm。
三、应用范围
RX8025T芯片广泛应用于各种需要高精度时钟的场合,如电表、水表、燃气表、电平转换、对EMI灵敏的收发器应用、工业控制、门禁、安防系统等领域。
四、版本差异
- RX8025T UB:工业级产品,使用温度范围更大,适合在极端环境下使用。
- RX8025T UC:民用级或商业级产品,使用温度范围相对较小,但更适合日常使用。基于性能的不同,价格方面RX8025T UB要比RX8025T UC略贵一些。不过差距并不大,用户可以根据自己的需求来选择。
五、注意事项
有用户反馈RX8025T芯片在某些情况下可能存在死机问题,且没有复位脚和软件复位功能。因此,在设计和使用过程中需要特别注意这一点,并采取相应的措施来避免或解决可能的问题。
总的来说,RX8025T是一款性能优异、功能丰富的高精度实时时钟芯片,广泛应用于各种电子设备中以确保准确的时间记录和计时功能。在选择和使用时,需要根据具体的应用场景和需求来选择合适的版本和采取相应的措施来确保芯片的稳定性和可靠性。
其c代码如下:
#include "RX8025T.h"
#include "stdlib.h"
#include "string.h"
tm DisplayInDateTime,DisplayInDateTime1;
/*************************************************
Copyright (C), JING LEI RECTIFIER. Co., Ltd.
File name: // i2c.c
Author: wangzhang
Version: V1.0
Date: // 2018-12-4
Description:
* This file contains I2C code drivers including GPIO
* initialization, and APIs for I2C access.
*************************************************/
/*===========================================================
功能描述:I2C GPIO初始化
参数: 无
返回: 无
============================================================*/
void I2CT_GPIOInit(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*===========================================================
功能描述:配置SDA(PB11)推挽输出
参数: 无
返回: 无
============================================================*/
void SDAT_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*===========================================================
功能描述:配置SDA(PB11)上拉输入
参数: 无
返回: 无
============================================================*/
void SDAT_IN(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*===========================================================
功能描述:I2C起始条件
参数: 无
返回: 无
============================================================*/
void I2CT_Start(void)
{
SDAT_OUT();
SCL_1;
SDA_1;
delay_us(10);
SDA_0;//START:when CLK is high,DATA change form high to low
delay_us(10);
SCL_0; //钳住I2C总线,准备发送或接收数据
delay_us(10);
}
/*===========================================================
功能描述:I2C停止条件
参数: 无
返回: 无
============================================================*/
void I2CT_Stop(void)
{
u8 i;
SDAT_OUT();//sda线输出
SCL_0;
SDA_0;//STOP:when CLK is high DATA change form low to high
delay_us(10);
SCL_1;
delay_us(10);
SDA_1;//发送I2C总线结束信号
for(i=0;i<5;i++)
{
delay_us(10);
}
}
/*===========================================================
功能描述:I2C等待应答信号到来
参数: 无
返回: 返回值:1,接收应答失败
0,接收应答成功
============================================================*/
u8 I2CT_Wait_Ack(void)
{
u8 ucErrTime=0;
SDAT_IN(); //SDA设置为输入
SDA_1;
delay_us(10);
SCL_1;
delay_us(10);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
I2CT_Stop();
return 1;
}
}
SCL_0;//时钟输出0
return 0;
}
/*===========================================================
功能描述:I2C发送Ack
参数: 无
返回: 无
============================================================*/
void I2CT_SendAck(void)
{
SDAT_OUT();
SDA_0;
delay_us(5);
SCL_1;
delay_us(5);
SCL_0;
delay_us(5);
}
/*===========================================================
功能描述:I2C发送NAck
参数: 无
返回: 无
============================================================*/
void I2CT_SendNAck(void)
{
SDAT_OUT();
SDA_1;
delay_us(5);
SCL_1;
delay_us(5);
SCL_0;
delay_us(5);
}
/*===========================================================
功能描述:I2C发送一个字节
参数: txd,数据
返回: TRUE,失败
FALSE,成功
============================================================*/
u8 I2CT_Send_Byte(u8 txd)
{
u8 i;
u8 ret;
SDAT_OUT();
for(i=0;i<8;i++)
{
if((txd&0x80)>>7) SDA_1;
else SDA_0;
txd <<= 1;
delay_us(10);
SCL_1;
delay_us(10);
SCL_0;
delay_us(10);
}
ret = I2CT_Wait_Ack();
return ret;
}
/*===========================================================
功能描述:I2C接收一个字节(8位)
参数: ack,收完一个字节是否产生应答位
返回: 接收的字节数据
注意事项:连续读取字节的情况下,ack一定要为TRUE
单个读取字节的时候,ack一定要为FALSE
============================================================*/
u8 I2CT_Rcv_Byte(u8 ack)
{
u8 i,receive=0;
SDAT_IN();//SDA设置为输入
for(i=0;i<8;i++)
{
SCL_1;
delay_us(10);
receive <<=1;
if(READ_SDA) receive |= 0x01;
SCL_0;
delay_us(10);
}
SDAT_OUT();
if (!ack)
I2CT_SendNAck();//发送nACK
else
I2CT_SendAck(); //发送ACK
return receive;
}
RTC_TIME_DEF stDateTime;
//DEVSTATE devState;
u8 pubRam[10];
const unsigned char* COMPLICE_DATA = __DATE__;//(注意是英文状态下两个_符号的)
const unsigned char* COMPLICE_TIME = __TIME__;
/*******************************************************************************
* Function Name : BCD2DEC
* Description : BCD码转二位十进制
* parameter : temp,BCD码
* Return : 对应数据的二位十进制
*******************************************************************************/
u8 BCD2DEC(u8 temp)
{
temp = (temp >> 4) * 10 + (temp & 0x0f);
return temp;
}
/*******************************************************************************
* Function Name : DEC2BCD
* Description : 二位十进制转BCD码
* parameter : temp,二位十进制
* Return : 数据BCD码
*******************************************************************************/
u8 DEC2BCD(u8 temp)
{
temp = (temp / 10) * 16 + (temp % 10);
return temp;
}
//void R8025AC_Read(u8 sadd, u8 *buf, u8 len)
//{
// IIC_Read_Buffer(sadd, buf, len, RX8025_ADDR_WRITE, RX8025_ADDR_READ);
//}
//
//void R8025AC_Write(u8 sadd,u8 *buf,u8 len)
//{
// IIC_Write_Buffer(sadd, buf, len, RX8025_ADDR_WRITE);
//}
//字符串截取
char *myStrncpy(char *dest, const char *src, int n)
{
int size = sizeof(char)*(n + 1);
char *tmp = (char*)malloc(size); // 开辟大小为n+1的临时内存tmp
if (tmp)
{
memset(tmp, '\0', size); // 将内存初始化为0
memcpy(tmp, src, size - 1); // 将src的前n个字节拷贝到tmp
memcpy(dest, tmp, size); // 将临时空间tmp的内容拷贝到dest
free(tmp); // 释放内存
return dest;
}
else
{
return NULL;
}
}
//得到软件编译时间?
COMPILE_TIME_DEF GetSoftWareBuildTargetTime(void)
{
char arrDate[20]; //Jul 03 2018
char arrTime[20]; //06:17:05
char pDest[20];
COMPILE_TIME_DEF stTime;
sprintf(arrDate,"%s",__DATE__);//Jul 03 2018
sprintf(arrTime,"%s",__TIME__);//06:17:05
//char *strncpy(char *dest, const char *src, int n)
//(char*)(&(pDest[0])) = myStrncpy(pDest, arrDate, 3);
sprintf(pDest, "%s", myStrncpy(pDest, arrDate, 3));
if (strcmp(pDest, "Jan") == 0) stTime.nMonth = 1;
else if (strcmp(pDest, "Feb") == 0) stTime.nMonth = 2;
else if (strcmp(pDest, "Mar") == 0) stTime.nMonth = 3;
else if (strcmp(pDest, "Apr") == 0) stTime.nMonth = 4;
else if (strcmp(pDest, "May") == 0) stTime.nMonth = 5;
else if (strcmp(pDest, "Jun") == 0) stTime.nMonth = 6;
else if (strcmp(pDest, "Jul") == 0) stTime.nMonth = 7;
else if (strcmp(pDest, "Aug") == 0) stTime.nMonth = 8;
else if (strcmp(pDest, "Sep") == 0) stTime.nMonth = 9;
else if (strcmp(pDest, "Oct") == 0) stTime.nMonth = 10;
else if (strcmp(pDest, "Nov") == 0) stTime.nMonth = 11;
else if (strcmp(pDest, "Dec") == 0) stTime.nMonth = 12;
else stTime.nMonth = 1;
sprintf(pDest, "%s", myStrncpy(pDest, arrDate+4, 2));
//int atoi(const char *nptr);
stTime.nDay = atoi(pDest);
sprintf(pDest, "%s", myStrncpy(pDest, arrDate + 4 + 3, 4));
//int atoi(const char *nptr);
stTime.nYear = atoi(pDest);
//time
sprintf(pDest, "%s", myStrncpy(pDest, arrTime, 2));
stTime.nHour = atoi(pDest);
sprintf(pDest, "%s", myStrncpy(pDest, arrTime+3, 2));
stTime.nMinute = atoi(pDest);
sprintf(pDest, "%s", myStrncpy(pDest, arrTime + 3 + 3, 2));
stTime.nSecond = atoi(pDest);
return stTime;
}
/*******************************************************************************
* Function Name : Get8025
* Description : 读取8025T i2c数据
* parameter : addr,起始地址
data,读数据缓冲区
counter,缓冲区数据长度
* Return : None
*******************************************************************************/
void Get8025( u8 addr, u8 *data,u8 counter)
{
u8 i;
I2CT_Start();
I2CT_Send_Byte(0x64);
I2CT_Send_Byte(addr);
I2CT_Start();
I2CT_Send_Byte(0x65);
for (i = 0; i < counter - 1 ; i++)
*data++ = I2CT_Rcv_Byte(1);
*data++ = I2CT_Rcv_Byte(0);
I2CT_Stop();
}
/*******************************************************************************
* Function Name : Set8025
* Description : 设置8025T i2c数据
* parameter : addr,起始地址
data,写数据缓冲区
counter,缓冲区数据长度
* Return : None
*******************************************************************************/
void Set8025( u8 addr, u8 *data,u8 counter)
{
u8 i;
I2CT_Start();
I2CT_Send_Byte(0x64);
I2CT_Send_Byte(addr);
for(i = 0; i <counter; i++)
I2CT_Send_Byte(*data++);
I2CT_Stop();
}
/*******************************************************************************
* Function Name : Init8025
* Description : 时钟芯片8025T初始化
* parameter : None
* Return : None
*******************************************************************************/
void Init8025(void)
{
u8 da[3];
da[0]=0x00;
da[1]=0x00; // 24小时模式设置,1Hz 频率输出
da[2]=0x60;
Set8025(RTC8025T_Control1,da,3);
memset(pubRam,0,3);
Get8025(RTC8025T_Control1,pubRam,3);
// if(pubRam[2] != da[2])
// {
// my_printf("RX8025T Init err\r\n");
// }
// else
// {
// my_printf("RX8025T Init ok\r\n");
// }
}
/*******************************************************************************
* Function Name : TimerDataHandle
* Description :
* parameter :
* Return : None
*******************************************************************************/
void TimerDataHandle(u8* pDate)
{
stDateTime.second = BCD2DEC(pDate[0]);
stDateTime.minute = BCD2DEC(pDate[1]);
if(pDate[2]==0x24)
pDate[2] = 0;
stDateTime.hour = BCD2DEC(pDate[2]);
if(pDate[3] == 0x01)
stDateTime.week = 0;
else if(pDate[3] == 0x02)
stDateTime.week = 1;
else if(pDate[3] == 0x04)
stDateTime.week = 2;
else if(pDate[3] == 0x08)
stDateTime.week = 3;
else if(pDate[3] == 0x10)
stDateTime.week = 4;
else if(pDate[3] == 0x20)
stDateTime.week = 5;
else if(pDate[3] == 0x40)
stDateTime.week = 6;
stDateTime.date = BCD2DEC(pDate[4]);
stDateTime.month = BCD2DEC(pDate[5]);
stDateTime.year = BCD2DEC(pDate[6]);
DisplayInDateTime.w_year = stDateTime.year+1900;
DisplayInDateTime.w_month= stDateTime.month = BCD2DEC(pDate[5])+1;
DisplayInDateTime.w_date = stDateTime.date ;
DisplayInDateTime.hour = stDateTime.hour ;
DisplayInDateTime.min = stDateTime.minute;
DisplayInDateTime.sec = stDateTime.second ;
}
//void RTCTimeDis(void)
//{
// my_printf ("%d:%d:%d\r\n ", 1900+stDateTime.year, stDateTime.month+1, stDateTime.date);
// my_printf("%d:%d:%d\n", stDateTime.hour, stDateTime.minute, stDateTime.second);
//}
/*******************************************************************************
* Function Name : RtcSetDateTime
* Description : 设置RTC时间
* parameter : 时间结构体
* Return : None
*******************************************************************************/
void RtcSetDateTime(RTC_TIME_DEF *pTime)
{
u8 Timebuf[7];
Timebuf[0] =
DEC2BCD(pTime->second);
Timebuf[1] =
DEC2BCD(pTime->minute);
Timebuf[2] =
DEC2BCD(pTime->hour);
Timebuf[3] =
(0x01)<<(pTime->week);
Timebuf[4] =
DEC2BCD(pTime->date);
Timebuf[5] =
DEC2BCD(pTime->month);
Timebuf[6] =
DEC2BCD(pTime->year);
Set8025(0,Timebuf,7); //Timebuf中数据为BCD码
TimerDataHandle(Timebuf);
}
/*******************************************************************************
* Function Name : RtcSetLocalTime
* Description : 更新本地时间
* parameter : None
* Return : None
*******************************************************************************/
void RtcSetLocalTime(void)
{
COMPILE_TIME_DEF now_ptm;
RTC_TIME_DEF set_time; //年月日时分秒都是BCD码
now_ptm = GetSoftWareBuildTargetTime();; //指针指向结构体中所存为十进制
// set_time.second = now_ptm.nSecond; //取值区间为[0,59]
set_time.minute = DisplayInDateTime1.min ; //取值区间为[0,59]
set_time.hour = DisplayInDateTime1.hour ; //取值区间为[0,23]
// set_time.week = now_ptm.nWeek; //取值区间为[0,6],0为星期天
set_time.date = DisplayInDateTime1.w_date; //取值区间为[1,31]
set_time.month =DisplayInDateTime1.w_month-1; //取值区间为[0,11] ,0为1月
set_time.year = DisplayInDateTime1.w_year-1900;//tm的年从1900开始计算
set_time.reserve = 0;
// sscanf(COMPLICE_DATA, "%u %d %d", weektemp, set_time.date, set_time.year);
// sscanf(COMPLICE_TIME, "%d:%d:%d", set_time.hour, set_time.minute, set_time.second);
// set_time.second = 0; //取值区间为[0,59]
// set_time.minute = 0; //取值区间为[0,59]
// set_time.hour = 0; //取值区间为[0,23]
// set_time.week = 1; //取值区间为[0,6],0为星期天
// set_time.date = 21; //取值区间为[1,31]
// set_time.month = 1; //取值区间为[0,11] ,0为1月
// set_time.year = 2019-1900;//tm的年从1900开始计算
// set_time.reserve = 0;
RtcSetDateTime(&set_time);
}
/*******************************************************************************
* Function Name : UpdateDateTime
* Description : 读取RTC寄存器并更新当前时间
* parameter : None
* Return : None
*******************************************************************************/
void UpdateDateTime(void)
{
u8 Timebuf[7];
Get8025(RTC8025_Second, Timebuf, 7); //Timebuf中数据为BCD码
TimerDataHandle(Timebuf);
}
///*******************************************************************************/
///* Task: taskCalendar_Rtc 实时更新日历显示 */
///*******************************************************************************/
//void taskCalendar_Rtc (void)
//{
//
// for (;;)
// {
// UpdateDateTime();//更新本地时间
// delay_ms(50);
// }
//}
其.h文件如下:
#ifndef __RX8025T_H__
#define __RX8025T_H__
#include "main.h"
#include <time.h>
/*
Private define-----------------------------------------------------------------------------*/
#define SCL_1 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET)
#define SCL_0 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET)
#define SDA_1 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET)
#define SDA_0 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET)
//#define READ_SCL GPIOB->IDR & GPIO_Pin_8
#define READ_SDA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3)
void SDA_IN(void);
void SDA_OUT(void);
void I2CT_GPIOInit(void);
void I2CT_Start(void);
void I2CT_Stop(void);
u8 I2CT_Wait_Ack(void);
void I2CT_SendAck(void);
void I2CT_SendNAck(void);
u8 I2CT_Send_Byte(u8 txd);
u8 I2CT_Rcv_Byte(u8 ack);
// 设备读写地址
#define RX8025_ADDR_READ 0x65
#define RX8025_ADDR_WRITE 0x64
// 设备寄存器地址
#define RX8025_ADDR_SECONDS 0x00
#define RX8025_ADDR_WEEK 0x30
#define RX8025_ADDR_DATES 0x40
#define RX8025_ADDR_MONTH 0x50
#define RX8025_ADDR_MINUTES 0x80
#define RX8025_ADDR_CONTROL1 0xE0
#define RX8025_ADDR_CONTROL2 0xF0
// 设备操作模式
#define RX8025_WRITE_MODE 0xF0
#define RX8025_READ_MODE 0xF0
#define RX8025_SIMP_READ_MODE 0x04
// 时间寄存器定义
#define RTC8025_Second 0 //秒寄存器
#define RTC8025_Minute 1 //分寄存器
#define RTC8025_Hour 2 //时寄存器
#define RTC8025_Week 3 //星期寄存器
#define RTC8025_Day 4 //日寄存器
#define RTC8025_Month 5 //月寄存器
#define RTC8025_Year 6 //年寄存器
// 控制寄存器定义(时钟芯片型号不相同,相应的配置也是不相同的)
#define RTC8025T_Control1 (0x0D) //控制1 寄存器 (R8025T)
#define RTC8025_Control1 (0x0E) //控制1 寄存器 (R8025AC)
#define RTC8025_PON (0x10) // RTC电源失效标志位
#define RTC8025_XST (0x20) // RTC内部晶振失效标志位
// 工作模式定义
#define RTC8025_Standard_Read (0x00) //标准读模式
#define RTC8025_Simple_Read (0x04) //简单读模式
//时间结构体
typedef struct
{
u8 nHour;
u8 nMinute;
u8 nSecond;
//公历日月年周
u8 nMonth;
u8 nDay;
u8 nWeek;
u16 nYear;
} COMPILE_TIME_DEF;
typedef struct
{
u8 second;
u8 minute;
u8 hour;
u8 week;
u8 date;
u8 month;
u8 year;
u8 reserve;
}RTC_TIME_DEF;
//RTC_TIME_DEF SET_TIME;
typedef struct
{
u8 hour;
u8 min;
u8 sec;
//公历日月年周
u16 w_year;
u8 w_month;
u8 w_date;
u8 week;
}tm;
extern tm DisplayInDateTime,DisplayInDateTime1;
void RTCTimeDis(void);
void R8025AC_Read(u8 sadd, u8 *buf, u8 len);
void R8025AC_Write(u8 sadd,u8 *buf,u8 len);
void Init8025(void);
void RtcSetDateTime(RTC_TIME_DEF *pTime);
void RtcSetLocalTime(void);
void UpdateDateTime(void);
void taskCalendar_Rtc (void);
extern RTC_TIME_DEF stDateTime;
extern RTC_TIME_DEF broadcast_time,save_time; //年月日星期都是BCD码
#endif
该程序为对应的STM32程序,使用时仅需要修改对应的IO口。调用读(UpdateDateTime() )写(RtcSetLocalTime)函数,读写的年份从1900年开始,月是0-11。就是说写入2025年2月,写入年为125,月为1,其他正常,在代码中都有注释。