#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; }