/*--------------------------------------------------------------------------*/ /**@file iic_io.c @brief IO模拟的IIC的驱动 @details @author zhiying @date 2013-3-26 @note */ /*----------------------------------------------------------------------------*/ #include "iic.h" /*----------------------------------------------------------------------------*/ /** @brief: IIC 模块初始化函数 @param: void @return:void @author:Juntham @note: void iic_init_io(void) */ /*----------------------------------------------------------------------------*/ void iic_init_io(void) { iic_data_h(); iic_data_out(); //SDA设置成输出 iic_clk_h(); iic_clk_out(); //SCL设置成输出 } /*----------------------------------------------------------------------------*/ /**@brief @param 无 @return @note */ /*----------------------------------------------------------------------------*/ void iic_start(void) { iic_init_io(); iic_delay(); iic_data_l(); iic_delay(); iic_clk_l(); iic_delay(); //iic_data_h(); } /*----------------------------------------------------------------------------*/ /**@brief STOP IIC @param 无 @return 无 @note void iic_stop(void) */ /*----------------------------------------------------------------------------*/ void iic_stop(void) { iic_data_out(); iic_data_l(); iic_delay(); iic_clk_h(); iic_delay(); iic_data_h(); iic_delay(); } /*----------------------------------------------------------------------------*/ /**@brief 读取ACK @param 无 @return 都会的ACK/NACK的电平 @note tbool r_ack(void) */ /*----------------------------------------------------------------------------*/ tbool r_ack(void) { tbool tnack; iic_data_in(); iic_delay(); iic_clk_h(); iic_delay(); iic_delay(); iic_delay(); iic_delay(); iic_delay(); tnack = iic_data_r(); iic_clk_l(); iic_delay(); return tnack; } /*----------------------------------------------------------------------------*/ /**@brief 发送一个ACK信号的数据, @param flag :发送的ACK/nack的类型 @return 无 @note void s_ack(u8 flag) */ /*----------------------------------------------------------------------------*/ void s_ack(u8 flag) { iic_data_out(); iic_clk_l(); if (flag) { iic_data_h(); } else { iic_data_l(); } iic_delay(); iic_clk_h(); iic_delay(); iic_clk_l(); } /*----------------------------------------------------------------------------*/ /**@brief 从IIC总线接收一个BYTE的数据, @param 无 @return 读取回的数据 @note u8 iic_revbyte_io( void ) */ /*----------------------------------------------------------------------------*/ tu8 iic_revbyte_io(void) { u8 tbyteI2C = 0X00; u8 i; iic_data_in(); iic_delay(); for (i = 0; i < 8; i++) { iic_clk_h(); tbyteI2C <<= 1; iic_delay(); if (iic_data_r()) { tbyteI2C++; } iic_clk_l(); iic_delay(); } return tbyteI2C; } /*----------------------------------------------------------------------------*/ /**@brief 从IIC总线接收一个BYTE的数据,并发送一个指定的ACK @param para :发送ACK 还是 NACK @return 读取回的数据 @note u8 iic_revbyte( u8 para ) */ /*----------------------------------------------------------------------------*/ tu8 iic_revbyte(u8 para) { u8 tbyte; tbyte = iic_revbyte_io(); s_ack(para); delay(30000); return tbyte; } /*----------------------------------------------------------------------------*/ /**@brief 向IIC总线发送一个BYTE的数据 @param byte :要写的EEROM的地址 @return 无 @note void iic_sendbyte_io(u8 byte) */ /*----------------------------------------------------------------------------*/ void iic_sendbyte_io(u8 byte) { u8 i; iic_data_out(); iic_delay(); //otp_printf("byte: %02x\n", byte); for (i = 0; i < 8; i++) { if (byte & BIT(7)) { iic_data_h(); //最高位是否为1,为1则SDA= 1,否则 SDA=0 } else { iic_data_l(); } iic_delay(); iic_clk_h(); iic_delay(); byte <<= 1; //数据左移一位,进入下一轮送数 iic_clk_l(); iic_delay(); } } /*----------------------------------------------------------------------------*/ /**@brief 向IIC总线发送一个BYTE的数据,并读取ACK @param byte :要写的EEROM的地址 @return 无 @note void iic_sendbyte(u8 byte) */ /*----------------------------------------------------------------------------*/ void iic_sendbyte(u8 byte) { iic_sendbyte_io(byte); r_ack(); delay(30000); } ///------------------------------------------------------------------------------ ///------------------------------------IIC_API----------------------------------- ///------------------------------------------------------------------------------ bool g_iic_busy = 0; /// 0; n--) { iic_sendbyte(*iic_dat++); //写数据 } iic_stop(); //I2C停止时序 g_iic_busy = 0; } /*----------------------------------------------------------------------------*/ /**@brief IIC总线向一个目标ID读取几个数据 @param address : 目标ID @param *p : 存档读取到的数据的buffer指针 @param number : 需要读取的数据的个数 @return 无 @note void i2c_read_nbyte(u8 address,u8 *p,u8 number) */ /*----------------------------------------------------------------------------*/ void iic_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n) { g_iic_busy = 1; iic_start(); //I2C启动 iic_sendbyte(chip_id); //写命令 if (0xff != iic_addr) { iic_sendbyte(iic_addr); //写地址 } for (; n > 1; n--) { *iic_dat++ = iic_revbyte(0); //读数据 } *iic_dat++ = iic_revbyte(1); iic_stop(); //I2C停止时序 g_iic_busy = 0; } /*----------------------------------------------------------------------------*/ /**@brief EEROM/RTC RAM读函数 @param addr :要写的EEROM/RTC RAM的地址 @return 读到的数据 @note u8 read_info(u8 addr) */ /*----------------------------------------------------------------------------*/ tu8 read_info(u8 addr) { return read_eerom(addr); } /*----------------------------------------------------------------------------*/ /**@brief EEROM/RTC RAM写函数 @param addr :要读的EEROM/RTC RAM的地址 @param dat :需要读的数据 @return 无 @note void write_info(u8 addr,u8 dat) */ /*----------------------------------------------------------------------------*/ void write_info(u8 addr, u8 dat) { write_eerom(addr, dat); } /*----------------------------------------------------------------------------*/ /**@brief eeprom START @param 无 @return 无 @note void eeprom_page_write_start(void) */ /*----------------------------------------------------------------------------*/ void eeprom_page_write_start(void) { g_iic_busy = 1; iic_start(); //I2C启动 iic_sendbyte(0xa0); //写命令 } /*----------------------------------------------------------------------------*/ /**@brief IIC STOP @param 无 @return 无 @note void eeprom_page_write_stop(void) */ /*----------------------------------------------------------------------------*/ void eeprom_page_write_stop(void) { iic_stop(); //I2C停止iic_data_out g_iic_busy = 0; } /*----------------------------------------------------------------------------*/ /**@brief EEROM读函数 @param addr :要写的EEROM的地址 @param 无 @return 无 @note u8 iic_read(u8 iic_addr) */ /*----------------------------------------------------------------------------*/ tu8 read_eerom(u8 iic_addr) { u8 tbyte; g_iic_busy = 1; iic_start(); //I2C启动 iic_sendbyte(0xa0); //写命令 iic_sendbyte(iic_addr); //写地址 iic_start(); //写转为读命令,需要再次启动I2C iic_sendbyte(0xa1); //读命令 tbyte = iic_revbyte(1); iic_stop(); //I2C停止 g_iic_busy = 0; return tbyte; } /*----------------------------------------------------------------------------*/ /**@brief 带有毫秒延时的EEROM写函数 @param addr :要写的EEROM的地址 @param dat :需要写的数据 @return 无 @note void write_info(u8 addr,u8 dat) */ /*----------------------------------------------------------------------------*/ void write_eerom(u8 addr, u8 dat) { iic_write(0xa0, addr, &dat, 1); iic_delay(); iic_delay(); iic_delay(); iic_delay(); iic_delay(); iic_delay(); } /*----------------------------------------------------------------------------*/ /** @brief: 记忆信息到存储器(EEPROM) @param: void @return:void @author:Juntham @note: void set_memory(u8 addr, u8 dat) */ /*----------------------------------------------------------------------------*/ void set_memory(u8 addr, u8 dat) { write_eerom(addr, dat); } /*----------------------------------------------------------------------------*/ /** @brief: 获取记忆信息(EEPROM) @param: void @return:void @author:Juntham @note: u8 get_memory(u8 addr) */ /*----------------------------------------------------------------------------*/ u8 get_memory(u8 addr) { return read_eerom(addr); }