637 lines
18 KiB
C
Raw Normal View History

2026-05-10 21:35:40 +08:00
#include "PCF8563.h"
/* 用户自定义头文件*/
#include "public_diy.h"
#include "bsp_timer.h"
// #include "system_stm32f10x.h"
// #define SYSTEM_CORE_CLOCK_VAL (SystemCoreClock)
#define PCF8563_SLAVE_ADDR (0x51)
#define PCF8563_READ (1u)
#define PCF8563_WRITE (0u)
#define PCF8563_DELAY_US(val) (bsp_DelayUS(val))
#define PCF8563_DELAY_MS(val) (bsp_DelayMS(val))
typedef struct
{
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t day;
uint8_t week;
uint8_t month;
uint8_t year;
/* data */
}pcf8563_rtc_infor_Str;
static uint8_t pcf8563_init(void);
static uint8_t pcf8563_reboot(void);
static uint8_t pcf8563_set_rtc(rtc_time_infor rtc_infor);
static uint8_t pcf8563_read_rtc(rtc_time_infor * rtc_infor);
rtc_drv_str pcf8563_drv =
{
.rtc_type = RTCTYPE_PCF8563,
.init = pcf8563_init,
.reboot = pcf8563_reboot,
.get_rtc_time = pcf8563_read_rtc,
.set_rtc_time = pcf8563_set_rtc,
};
/* ========================================= 用户自定义驱动函数 ========================================== */
/*************************************************************************************
* @brief pcf8563使用的延时函数 us
* @param[in/out] val_us
*
* @warning ,
* @note
*************************************************************************************/
// void PCF8563_DELAY_US(uint16_t val_us)
// {
// bsp_DelayUS(val_us);
// }
/*************************************************************************************
* @brief pcf8563使用的延时函数 ms
* @param[in/out] val_ms
*
* @warning ,
* @note
*************************************************************************************/
// static void PCF8563_DELAY_MS(uint16_t val_ms)
// {
// bsp_DelayMS(val_ms);
// }
/*************************************************************************************
* @brief pcf8563
*
* @warning ,
* @note
*************************************************************************************/
static void pcf8563_start_signal(void)
{
if(rtc_is_SDA_as_openDrain_output() == 0)
{
rtc_SDA_as_output();
}
RTC_W_SCL(1);
RTC_W_SDA(1);
// 不知道要延迟多久 先延迟这么多
// PCF8563_DELAY_MS(1);
PCF8563_DELAY_US(1);
RTC_W_SDA(0);
// 延迟 大于等于 0.6us
PCF8563_DELAY_US(1);
RTC_W_SCL(0);
}
/*************************************************************************************
* @brief pcf8563
*
* @warning ,
* @note
*************************************************************************************/
static void pcf8563_stop_signal(void)
{
if(rtc_is_SDA_as_openDrain_output() == 0)
{
rtc_SDA_as_output();
}
RTC_W_SDA(0);
RTC_W_SCL(1);
// 延迟 大于等于 4us
PCF8563_DELAY_US(5);
RTC_W_SDA(1);
}
// /*************************************************************************************
// * @brief 读取pcf8563的Ack
// * @return uint8_t 【返回值注释】
// *
// * @warning 【不可重入,阻塞等警告】
// * @note 【重大修改】
// *************************************************************************************/
// uint8_t pcf8563_readAck(void)
// {
// uint8_t retVal;
// // uint8_t tmp_timeout = 3;
// rtc_SDA_as_input();
// RTC_W_SCL(1);
// PCF8563_DELAY_US(2);
// // 判断ack
// if(GET_RTC_SDA_STATE() == 0)
// {
// retVal = RET_OK;
// }
// else
// {
// retVal = RET_ERROR;
// }
// // 本周期剩下的低电平
// RTC_W_SCL(0);
// PCF8563_DELAY_US(2);
// // sda设为输出
// rtc_SDA_as_output();
// return retVal;
// }
// /*************************************************************************************
// * @brief 主动发送 NACK
// *
// * @warning 【不可重入,阻塞等警告】
// * @note 【重大修改】
// *************************************************************************************/
// void pcf8563_sendNAck(void)
// {
// rtc_SDA_as_output();
// // NACK
// RTC_W_SDA(1);
// // 本周期 高电平
// RTC_W_SCL(1);
// PCF8563_DELAY_US(2);
// // 本周期剩下的低电平
// RTC_W_SCL(0);
// PCF8563_DELAY_US(2);
// }
/*************************************************************************************
* @brief I2C发送一个字节
* @param[in/out] Byte
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
void pcf8563_sendByte(uint8_t Byte)
{
uint8_t i;
if(rtc_is_SDA_as_openDrain_output() == 0)
{
rtc_SDA_as_output();
}
// RTC_W_SDA(0);
for (i = 0; i < 8; i++)
{
RTC_W_SDA(!!(Byte & (0x80 >> i)));
RTC_W_SCL(1);
PCF8563_DELAY_US(2);
RTC_W_SCL(0);
PCF8563_DELAY_US(2);
}
}
/*************************************************************************************
* @brief pcf8563一字节数据
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
uint8_t pcf8563_recvByte(void)
{
uint8_t recv_val = 0;
uint8_t tmp_i = 0;
/* #### 主机释放SDA 如何释放? */
RTC_W_SDA(1);
/* 转为输入 */
if(rtc_is_SDA_as_floating_input() == 0)
{
rtc_SDA_as_input();
}
/* 主机接收数据 */
for(tmp_i = 0; tmp_i < 8; ++tmp_i)
{
RTC_W_SCL(1);
PCF8563_DELAY_US(2);
recv_val <<= 1;
recv_val |= GET_RTC_SDA_STATE();
RTC_W_SCL(0);
PCF8563_DELAY_US(2);
}
return recv_val;
}
/*************************************************************************************
* @brief ack
* @param[in/out] val
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_send_ACK(uint8_t val)
{
/* SDA设为输出 */
if(rtc_is_SDA_as_openDrain_output() == 0)
{
rtc_SDA_as_output();
}
/* SDA主动发送val相应的电平 */
RTC_W_SDA(val);
/* SCL置为1 使val电平状态保持 延迟2us*/
RTC_W_SCL(1);
PCF8563_DELAY_US(2);
/* SCL置为1 本周期剩下的低电平 延迟2us*/
RTC_W_SCL(0);
PCF8563_DELAY_US(2);
/* 结束逻辑 返回成功 */
return RET_OK;
}
/*************************************************************************************
* @brief ACK ACK结果
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_wait_ACK(void)
{
uint8_t retVal = RET_ERROR;
uint8_t wait_timer = 2;
/* #### 主机释放SDA 如何释放? */
RTC_W_SDA(1);
/* 转为输入 */
if(rtc_is_SDA_as_floating_input() == 0)
{
rtc_SDA_as_input();
}
/* 延迟1us */
PCF8563_DELAY_US(1);
/* SCL 拉高 */
RTC_W_SCL(1);
/* 超时最多2us 等待SDA为低 */
while(wait_timer > 0 && GET_RTC_SDA_STATE() > 0)
{
wait_timer--;
PCF8563_DELAY_US(1);
}
/* 根据SDA状态 判断是否成功接收 */
if(GET_RTC_SDA_STATE() == 0)
{
retVal = RET_OK;
}
else
{
retVal = RET_ERROR;
}
/* SCL 拉低 */
RTC_W_SCL(0);
/* 延迟2us */
PCF8563_DELAY_US(2);
return retVal;
}
/*************************************************************************************
* @brief pcf8563内
* @param[in/out] addr
* @param[in/out] byte
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
uint8_t pcf8563_write_one_byte(uint8_t addr, uint8_t byte)
{
uint8_t tmp_retVal = RET_ERROR;
uint8_t tmp_addr_rw = 0;
/* 1. 开始信号 */
pcf8563_start_signal();
/* 2. 第一个数据 从设备地址+读写状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_WRITE;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 3. 发字地址 */
pcf8563_sendByte(addr);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 4. 发数据 */
pcf8563_sendByte(byte);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 5. 停止信号 */
pcf8563_stop_signal();
return RET_OK;
}
/*************************************************************************************
* @brief pcf8563内
* @param[in/out] addr
* @param[in/out] buf
* @param[in/out] len
* @return uint8_t RET_INVALID RET_OK: RET_ERROR
*
* @warning ,
* @note
*************************************************************************************/
uint8_t pcf8563_write_bytes(uint8_t addr, uint8_t *buf, uint16_t len)
{
uint8_t tmp_retVal = RET_ERROR;
uint8_t tmp_i;
uint8_t tmp_addr_rw = 0;
/* 合法性校验 */
if(len == 0 || buf == NULL)
{
return RET_INVALID;
}
/* 1. 开始信号 */
pcf8563_start_signal();
/* 2. 第一个数据 从设备地址+读写状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_WRITE;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 3. 发字地址 */
pcf8563_sendByte(addr);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 4. 发连续地址的数据 */
for(tmp_i = 0; tmp_i < len; ++tmp_i)
{
pcf8563_sendByte(buf[tmp_i]);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
}
/* 5. 停止信号 */
pcf8563_stop_signal();
return RET_OK;
}
/*************************************************************************************
* @brief pcf8563内
* @param[in/out] addr
* @param[in/out] byte
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
uint8_t pcf8563_read_one_byte(uint8_t addr, uint8_t *byte)
{
uint8_t tmp_retVal = RET_ERROR;
uint8_t tmp_addr_rw = 0;
// uint8_t tmp_value = 0;
/* 1. 开始信号 */
pcf8563_start_signal();
/* 2. 第一个数据 从设备地址+读写状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_WRITE;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 3. 发字地址 */
pcf8563_sendByte(addr);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 4. 发重新开始信号 */
pcf8563_start_signal();
/* 5. 再次发第一个数据 从设备地址 + 读状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_READ;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 6. 接收一字节数据 */
*byte = pcf8563_recvByte();
/* send ACK */
pcf8563_send_ACK(1);
/* 7. 停止信号 */
pcf8563_stop_signal();
return RET_OK;
}
/*************************************************************************************
* @brief pcf8563内
* @param[in/out] addr
* @param[in/out] buf
* @param[in/out] len
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
uint8_t pcf8563_read_bytes(uint8_t addr, uint8_t *buf, uint16_t len)
{
uint8_t tmp_retVal = RET_ERROR;
uint8_t tmp_addr_rw = 0;
// uint8_t tmp_value = 0;
uint8_t tmp_i;
/* 有效性检测 */
if(len == 0 || buf == NULL)
{
return RET_INVALID;
}
/* 1. 开始信号 */
pcf8563_start_signal();
/* 2. 第一个数据 从设备地址+读写状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_WRITE;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 3. 发字地址 */
pcf8563_sendByte(addr);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 4. 发重新开始信号 */
pcf8563_start_signal();
/* 5. 再次发第一个数据 从设备地址 + 读状态 */
// 发送从设备地址 写
tmp_addr_rw = (PCF8563_SLAVE_ADDR << 1) + PCF8563_READ;
pcf8563_sendByte(tmp_addr_rw);
/* wait ack*/
tmp_retVal = pcf8563_wait_ACK();
if(tmp_retVal == RET_ERROR)
{
pcf8563_stop_signal();
return RET_ERROR;
}
/* 6. 接收多个字节数据 */
for(tmp_i = 0; tmp_i < len; ++tmp_i)
{
buf[tmp_i] = pcf8563_recvByte();
if(tmp_i == (len - 1))
{
pcf8563_send_ACK(1);
}
else
{
pcf8563_send_ACK(0);
}
}
/* send ACK */
/* 7. 停止信号 */
pcf8563_stop_signal();
return RET_OK;
}
/*************************************************************************************
* @brief pcf8563
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_init(void)
{
return RET_OK;
}
/*************************************************************************************
* @brief PCF8563
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_reboot(void)
{
/* 暂时还没研究 先设为无效 */
return RET_INVALID;
}
/*************************************************************************************
* @brief pcf8563 rtc值
* @param[in/out] rtc_infor
* @return uint8_t
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_read_rtc(rtc_time_infor * rtc_infor)
{
uint8_t retVal = RET_ERROR;
pcf8563_rtc_infor_Str str_pcf8563_rtc_info;
/* 合法性检验 */
if(rtc_infor == NULL)
{
return RET_INVALID;
}
/* 读取rtc数据 */
retVal = pcf8563_read_bytes(0x02, (u8*)&str_pcf8563_rtc_info, sizeof(str_pcf8563_rtc_info));
/* 取需要用到的部分 */
str_pcf8563_rtc_info.second &= 0x7F;
str_pcf8563_rtc_info.minute &= 0x7F;
str_pcf8563_rtc_info.hour &= 0x3F;
str_pcf8563_rtc_info.day &= 0x3F;
str_pcf8563_rtc_info.week &= 0x07;
str_pcf8563_rtc_info.month &= 0x1F;
/* 装填数据 */
rtc_infor->year = str_pcf8563_rtc_info.year;
rtc_infor->month = str_pcf8563_rtc_info.month;
rtc_infor->day = str_pcf8563_rtc_info.day;
rtc_infor->week = str_pcf8563_rtc_info.week;
rtc_infor->hour = str_pcf8563_rtc_info.hour;
rtc_infor->minute = str_pcf8563_rtc_info.minute;
rtc_infor->second = str_pcf8563_rtc_info.second;
/* 返回 */
return retVal;
}
/*************************************************************************************
* @brief pcf8563 rtc的值
*
* @warning ,
* @note
*************************************************************************************/
static uint8_t pcf8563_set_rtc(rtc_time_infor rtc_infor)
{
uint8_t retVal = RET_ERROR;
pcf8563_rtc_infor_Str str_pcf8563_rtc_info;
/* 装填数据 准备下设 */
str_pcf8563_rtc_info.year = rtc_infor.year;
str_pcf8563_rtc_info.month = rtc_infor.month;
str_pcf8563_rtc_info.day = rtc_infor.day;
str_pcf8563_rtc_info.week = rtc_infor.week;
str_pcf8563_rtc_info.hour = rtc_infor.hour;
str_pcf8563_rtc_info.minute = rtc_infor.minute;
str_pcf8563_rtc_info.second = rtc_infor.second;
/* 设置rtc数据 */
retVal = pcf8563_write_bytes(0x02, (u8*)&str_pcf8563_rtc_info, sizeof(str_pcf8563_rtc_info));
return retVal;
}