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_ */
初始化完毕后可直接读写该芯片