很多嵌入式设备在使用过程中,会碰到未联网的状态,但是有需要保证时间的正常,或者定时开关机功能。这个时候就需要添加RTC 时钟模块。下面通过mstar 平台的rx8130ce 型号时钟调试为例,一起分享。
RTC HW 连接
从HW提供的原理图设计时,提供了两款RTC 时钟芯片,地址分别是0x64,0xD0。
从提供的PCB 板上,UT3 未上件。 我们进一步查询I2C 的连接走线。
分析完原理图,要确保硬件的一下几点正常:
- RTC 的power 连接正常,电池(待机/断电时供电)和主板(上电时)
- RTC 的I2C 和主芯片的连接正常;
- RTC 的I2C 地址 的确定;
I2C 地址配置
找到pin 脚定义,然后配置总线,设置delay 时间,接着在总线下面挂载设备。
//Bus Info Define
#define BOARD_I2C_SWBUS_NUM 3
#define BOARD_I2C_HWBUS_NUM 0
#define BOARD_I2C_DEVICE_NUM 6static SWI2CBus_t BOARD_I2C_SWBUS[BOARD_I2C_SWBUS_NUM]=
{//Example for SW I2C => { 1, PAD_DDCR_CK, PAD_DDCR_DA, 60, }, //SW_I2C /SCL_PAD /SDA_PAD /Delay// Bus-0{PAD_DDCR_CK, PAD_DDCR_DA, 100}, //IS_SW_I2C /SCL_PAD /SDA_PAD /Delay// Bus-1{PAD_TGPIO0 , PAD_TGPIO1, 100},// Bus-2{PAD_GPIO19 , PAD_GPIO20,100},// Bus-3//{PAD_GPIO2 , PAD_GPIO3,100},
};static HWI2CBus_t BOARD_I2C_HWBUS[BOARD_I2C_HWBUS_NUM];//Device Info Define
static I2CDeviceInfo_s Board_I2C_Dev[BOARD_I2C_DEVICE_NUM] =
{//Example => { TUNER1, 1, 0xC2 }, //gID(U32) /i2c_bus(U8) /slave_id(U8){TUNER1 , 1, 0xC0}, //gID(U32) /i2c_bus(U8) /slave_id(U8)// AD82088{AMP_SLAVER_ID , 1, 0x62}, // 0x31 << 1 --> 0x62// RTC{RTC_I2C_ID , 1, 0x64},// temp R/W{TMP102_CHIP_R , 1, 0x90},{TMP102_CHIP_W , 1, 0x91},// TCA9535{TCA9539_I2C_ID , 2, 0xE8}, // 0x74 << 1 = 0xE8
};
{RTC_I2C_ID , 1, 0x64}, 就是挂载第二组总线上的RTC,地址为0x64.
I2C 的读写
注意上面的RTC8130_SECADDR 是 RTC 的寄存器地址,跟时间日期相关的几个寄存器地址如下:
#define RTC8130_SLAVEADDR 0x64
#define RTC8130_SECADDR 0x10
#define RTC8130_MINADDR 0x11
#define RTC8130_HOURADDR 0x12
#define RTC8130_WEEKADDR 0x13
#define RTC8130_DATEADDR 0x14
#define RTC8130_MONTHADDR 0x15
#define RTC8130_YEARADDR 0x16
这些地址在协议里面会有说明。
RTC 时间数据格式
分析datasheet 中RTC 时间格式,其中秒,分,时,天,月,年 都是BCD 码格式存储。周 的存储方法不一样,按照所在的bit 位标记为第几周,一个月最多跨6 周。
- 设置时间
static MAPI_U8 HEX2BCD(MAPI_U8 cHEXData)
{MAPI_U8 cTemp;cTemp = ((cHEXData / 10) << 4) | (cHEXData % 10);return cTemp;
}
先将16进制的数据转换成BCD 码,然后设置到对应寄存器中。
SecAdd = RTC8130_SECADDR; // 0x10TimeTable[RTC_SECOND] = HEX2BCD(RTC8130_TimeData.param[RTC_SECOND]) & 0x7F;TimeTable[RTC_MINUTE] = HEX2BCD(RTC8130_TimeData.param[RTC_MINUTE]) & 0x7F;TimeTable[RTC_HOUR] = HEX2BCD(RTC8130_TimeData.param[RTC_HOUR]) & 0x3F;TimeTable[RTC_WEEK] = RTC8130_TimeData.param[RTC_WEEK] & 0x7F ;TimeTable[RTC_DATE] = HEX2BCD(RTC8130_TimeData.param[RTC_DATE]) & 0x3F;TimeTable[RTC_MONTH] = HEX2BCD(RTC8130_TimeData.param[RTC_MONTH]) & 0x1F;TimeTable[RTC_YEAR] = HEX2BCD(RTC8130_TimeData.param[RTC_YEAR]) & 0xFF;ret = iptr->WriteBytes(1,&SecAdd,7,&TimeTable[RTC_SECOND]);
- 获取时间
mapi_i2c *iptr = NULL;MAPI_U8 regAddr = RTC8130_SECADDR;RX8130_PRINTF(printf("[%s][%d] RX81390 Enter .\n",__FUNCTION__,__LINE__));iptr = mapi_i2c::GetI2C_Dev(RTC_I2C_ID);if(iptr == NULL){printf("[%s][%d] RX81390 Invalid I2c rtc addr .\n", __FUNCTION__,__LINE__);return MAPI_FALSE;}ret = iptr->ReadBytes(1, ®Addr, 7, TimeTable);if(MAPI_FALSE == ret){printf("[%s][%d] RX81390 Read ret = %d\n", __FUNCTION__,__LINE__,ret);return MAPI_FALSE;}RTC8130_TimeData.param[RTC_SECOND] = BCD2HEX(TimeTable[0]);RTC8130_TimeData.param[RTC_MINUTE] = BCD2HEX(TimeTable[1]);RTC8130_TimeData.param[RTC_HOUR] = BCD2HEX(TimeTable[2]);RTC8130_TimeData.param[RTC_WEEK] = TimeTable[3] & 0x7F;RTC8130_TimeData.param[RTC_DATE] = BCD2HEX(TimeTable[4]);RTC8130_TimeData.param[RTC_MONTH] = BCD2HEX(TimeTable[5]);RTC8130_TimeData.param[RTC_YEAR] = BCD2HEX(TimeTable[6]);
将读取到的BCD码转换成16进制数据给上层使用。
static MAPI_U8 BCD2HEX(MAPI_U8 cBCDData)
{MAPI_U8 cTemp;cTemp = ((cBCDData >> 4) * 10) + ( cBCDData & 0x0F);return cTemp;
}
另外要主要周,年的范围。例如, 年的最大值 165
(80+40+20+10+8+4+2+1),那么实际使用的需要补齐。
2019 年则传入RTC时是19,1970 传入应该是70 。一般定时也不多超过100年,所以还是能够满足实际要求的。
RTC 初始配置
datasheet 显示 Extension Register,Flag Register,Control Register0,Control Register1 需要设置默认状态。
RX8130_CONFIG g_RX8130_CONFIGData[] =
{{0x30,0x80},//enable DTE{0x1c,0x04},{0x1d,0x06},{0x1e,0x00},{0x1f,0x00},
};
iptr = mapi_i2c::GetI2C_Dev(RTC_I2C_ID);if(iptr == NULL){printf("[%s][%d] RX81390 Invalid I2c mcu addr .\n",__FUNCTION__,__LINE__);return ret;}for(i=0; i<sizeof(g_RX8130_CONFIGData)/sizeof(g_RX8130_CONFIGData[0]); i++){unAddr = g_RX8130_CONFIGData[i].RX8130_Address;unData = g_RX8130_CONFIGData[i].RX8130_InitData;ret = iptr->WriteBytes(1, &unAddr, 1, &unData);RX8130_PRINTF(printf("[%s][%d] RX8130 Write [0x%02x : 0x%02X] ret = %d\n",__FUNCTION__,__LINE__,unAddr,unData,ret));}return ret;
按照对应bit 位将初始值设入寄存器即可完成初始化,后面就可以正常设置,获取时间。
驱动源码
https://download.csdn.net/download/kehyuanyu/11987005