RTC 時鐘芯片已有很多可以選擇,RX-8025T內部已經集成年月日,星期和鬧鐘等功能無需軟件計算,使用起來很方便,搜索該芯片資料很多人都說資料勘誤,但我這個芯片按照資料操作並沒有問題,奉上代碼:
底層IIC驅動部分,採用IO模擬方式,DSP自帶的IIC模塊總是卡住,不好用》_》
#define SDA_IN() GPIO_SetupPinOptions(0, 0, 0)
#define SDA_OUT() GPIO_SetupPinOptions(0, 1, 0)
#define SDA_OUT_1() GPIO_WritePin(0, 1)
#define SDA_OUT_0() GPIO_WritePin(0, 0)
#define SCL_OUT_1() GPIO_WritePin(1, 1)
#define SCL_OUT_0() GPIO_WritePin(1, 0)
#define READ_SDA GPIO_ReadPin(0) //輸入SDA
#define delay_us DELAY_US
DRV_I2C_EXT void i2c_init_A(void)
{
GPIO_SetupPinMux(0,GPIO_MUX_CPU1,0); //SDA_OUT
GPIO_SetupPinOptions(0, 1, 0);//OUT mode
GPIO_WritePin(0, 1); // SDA =1
GPIO_SetupPinMux(1,GPIO_MUX_CPU1,0); //SCL_OUT
GPIO_SetupPinOptions(1, 1, 0);//OUT mode
GPIO_WritePin(1, 1); // SCL =1
}
//產生IIC起始信號
DRV_I2C_EXT void IIC_Start(void)
{
SDA_OUT(); //sda線輸出
SDA_OUT_1();
SCL_OUT_1();
delay_us(4);
SDA_OUT_0();//START:when CLK is high,DATA change form high to low
delay_us(4);
SCL_OUT_0();//鉗住I2C總線,準備發送或接收數據
}
//產生IIC停止信號
DRV_I2C_EXT void IIC_Stop(void)
{
SDA_OUT();//sda線輸出
SCL_OUT_0();
SDA_OUT_0();//STOP:when CLK is high DATA change form low to high
delay_us(4);
SCL_OUT_1();
SDA_OUT_1();//發送I2C總線結束信號
delay_us(4);
}
//等待應答信號到來
//返回值:1,接收應答失敗
// 0,接收應答成功
DRV_I2C_EXT uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN(); //SDA設置爲輸入
SDA_OUT_1();delay_us(1);
SCL_OUT_1();delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
SCL_OUT_0();//時鐘輸出0
return 0;
}
//產生ACK應答
DRV_I2C_EXT void IIC_Ack(void)
{
SCL_OUT_0();
SDA_OUT();
SDA_OUT_0();
delay_us(2);
SCL_OUT_1();
delay_us(2);
SCL_OUT_0();
}
//不產生ACK應答
DRV_I2C_EXT void IIC_NAck(void)
{
SCL_OUT_0();
SDA_OUT();
SDA_OUT_1();
delay_us(2);
SCL_OUT_1();
delay_us(2);
SCL_OUT_0();
}
//IIC發送一個字節
//返回從機有無應答
//1,有應答
//0,無應答
DRV_I2C_EXT void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
SCL_OUT_0();//拉低時鐘開始數據傳輸
for(t=0;t<8;t++)
{
if(txd&0x80) //高位在前
SDA_OUT_1();
else
SDA_OUT_0();
txd<<=1;
delay_us(2);
SCL_OUT_1();
delay_us(2);
SCL_OUT_0();
delay_us(2);
}
}
//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK
DRV_I2C_EXT uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA設置爲輸入
for(i=0;i<8;i++ )
{
SCL_OUT_0();
delay_us(2);
SCL_OUT_1();
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//發送nACK
else
IIC_Ack(); //發送ACK
return receive;
}
應用部分C文件代碼:
/*
* RX_8025T.c
*
* Created on: 2019年8月24日
* Author: horli
*/
#define RX_8025T_GOLBAL 1
#include "RX_8025T.h"
#include "drv_i2c.h"
//讀取寄存器
static uint8_t RX8025_ReadReg(uint8_t reg_addr)
{
uint8_t temp=0;
IIC_Start();//S
IIC_Send_Byte(RX8025_ADDR_HDL);//Slave addr_0
IIC_Wait_Ack();//ACK_0
IIC_Send_Byte(reg_addr);//Address
IIC_Wait_Ack();//ACK_0
IIC_Start();//Sr
IIC_Send_Byte(RX8025_ADDR_HDL+1);//Slave addr_1
IIC_Wait_Ack();//ACK_0
temp=IIC_Read_Byte(1);//data ...
IIC_Stop();//P
return temp;
}
static void ReadData(uint8_t reg_addr,uint8_t* dat,uint8_t len)
{
IIC_Start();//S
IIC_Send_Byte(RX8025_ADDR_HDL);//Slave addr_0
IIC_Wait_Ack();//ACK_0
IIC_Send_Byte(reg_addr);//Address
IIC_Wait_Ack();//ACK_0
IIC_Start();//Sr
IIC_Send_Byte(RX8025_ADDR_HDL+1);//Slave addr_1
IIC_Wait_Ack();//ACK_0
while(len)
{
dat[0]=IIC_Read_Byte(1);//data ...+ACK_CPU
dat++;
len--;
}
IIC_Stop();//P
}
// 寫入寄存器
static void RX8025_WriteReg(uint8_t reg_addr ,uint8_t *dat ,uint8_t len)
{
IIC_Start(); //S
IIC_Send_Byte(RX8025_ADDR_HDL);//Slave addr_0
IIC_Wait_Ack(); //ACK_0
IIC_Send_Byte(reg_addr);//Address
IIC_Wait_Ack(); //ACK_0
while(len)
{
IIC_Send_Byte(*dat++);//data..
IIC_Wait_Ack();//ACK_0
len--;
}
IIC_Stop();//P
}
static uint8_t RX8025_BCD2DEC(uint8_t val)
{
uint8_t i;
i = val&0x0f; //按位與,i得到低四位數。
val >>= 4; //右移四位,將高四位移到低四位的位置,得到高四位碼值。
val &= 0x0f; //防止移位時高位補進1,只保留高四位碼值
val *= 10; //高位碼值乘以10
i += val; //然後與第四位碼值相加。
return i; //將得到的十進制數返回
}
/**
* @brief RX8025_DEC2BCD 十進制轉BCD碼
* @param val BCD碼
* @return
*/
static uint8_t RX8025_DEC2BCD(uint8_t val)
{
uint8_t i;
i = val/10; //取得十位
val %= 10; //取得個位
i <<= 4; //左移4位
i += val;
return i;
}
//芯片初始化
RX_8025T_EXT void RX8025_Init(void)
{
uint8_t temp=0;
i2c_init_A() ;//初始化IIC
//清除 VLF(電壓低標誌位)
//清除VDET(電壓檢測標誌位)
temp = RX8025_ReadReg(RX8025_FLAG_REG);
temp =temp&0x0C;
RX8025_WriteReg(RX8025_FLAG_REG,&temp,1);
return ;
}
// 讀取時間
RX_8025T_EXT void Gettime_RTC8025T(struct tm *rtc)
{
uint8_t temp[7];
ReadData(RX8025_SEC,temp,7);
rtc->tm_sec = RX8025_BCD2DEC(temp[0]&0x7f);
rtc->tm_min = RX8025_BCD2DEC(temp[1]&0x7f);
rtc->tm_hour = RX8025_BCD2DEC(temp[2]&0x7f);
rtc->tm_wday= RX8025_BCD2DEC(temp[3]&0x07);
rtc->tm_mday = RX8025_BCD2DEC(temp[4]&0x3f);
rtc->tm_mon = RX8025_BCD2DEC(temp[5]&0x1f);
rtc->tm_year = RX8025_BCD2DEC(temp[6]&0xff);
rtc->tm_year += 2000;
return;
}
//設置時間
RX_8025T_EXT void Settime_RTC8025T(struct tm *rtc)
{
uint8_t temp[7];
temp[0] =RX8025_DEC2BCD(rtc->tm_sec);
temp[1] =RX8025_DEC2BCD(rtc->tm_min);
temp[2] =RX8025_DEC2BCD(rtc->tm_hour);
temp[3] =RX8025_DEC2BCD(rtc->tm_wday);
temp[4] =RX8025_DEC2BCD(rtc->tm_mday);
temp[5] =RX8025_DEC2BCD(rtc->tm_mon);
temp[6] =RX8025_DEC2BCD(rtc->tm_year-2000);
RX8025_WriteReg(RX8025_SEC,temp,7);
}
H文件代碼:
/*
* RX_8025T.h
*
* Created on: 2019年8月24日
* Author: horli
*/
#ifndef SOURCE_APP_RTC_RX8025_RX_8025T_H_
#define SOURCE_APP_RTC_RX8025_RX_8025T_H_
#ifndef RX_8025T_GOLBAL
#define RX_8025T_EXT
#else
#define RX_8025T_EXT extern
#endif
#include <time.h>
#include "stdint.h"
#define uint8_t unsigned char
#define RX8025_ADDR_HDL 0x64
// 設備寄存器地址
#define RX8025_SEC 0x00
#define RX8025_MIN 0x10
#define RX8025_HOUR 0x20
#define RX8025_WEEK 0x30
#define RX8025_DAY 0x40
#define RX8025_MONTH 0x50
#define RX8025_YEAR 0x60
#define RX8025_RAM 0x70
#define RX8025_MIN_ALM 0x80
#define RX8025_HOUR_ALM 0x90
#define RX8025_WK_DAY_ALM 0xA0
#define RX8025_TIM_CNT0 0xB0
#define RX8025_TIM_CNT1 0xC0
#define RX8025_EXT_REG 0xD0
#define RX8025_FLAG_REG 0xE0
#define RX8025_CTRL_REG 0xF0
RX_8025T_EXT void RX8025_Init(void);
RX_8025T_EXT void Gettime_RTC8025T(struct tm *rtc);
RX_8025T_EXT void Settime_RTC8025T(struct tm *rtc);
#endif /* SOURCE_APP_RTC_RX8025_RX_8025T_H_ */
初始化完畢後可直接讀寫該芯片