#include "drv_i2c.h" #include "drv_gpio.h" #include "kit_data.h" #include "kit_time.h" typedef struct { uint8_t clk_dly; //单位us uint8_t scl_io; uint8_t sda_io; uint32_t err_cnt; }I2cItem; I2cItem i2c_item[kI2cDev_End]; kit_ret_e drv_i2c_init(I2cDev dev, uint32_t freq, uint8_t scl_idx, uint8_t sda_idx) { I2cItem *item = &i2c_item[dev]; item->scl_io = scl_idx; item->sda_io = sda_idx; item->clk_dly = 1000 / freq; return kKit_Ret_Ok; } void drv_i2c_start(I2cItem *item) { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);; kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low); kit_time_dly_us(item->clk_dly); } void drv_i2c_stop(I2cItem *item) { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); } kit_ret_e i2c_sync_write_byte(I2cItem *item, uint8_t data) { kit_ret_e res = kKit_Ret_Error; uint32_t i; for(i = 0; i < 8; i++) { if((data & 0x80) == 0) { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low); } else { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); } kit_time_dly_us(2); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low); data <<= 1; kit_time_dly_us(item->clk_dly); } drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Input_Floating); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); if(drv_gpio_get_pin_status(item->sda_io) == kGpioStatus_Low) { res = kKit_Ret_Ok; } else { item->err_cnt++; } drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low); drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Output_PP); drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); return res; } uint8_t i2c_sync_read_byte(I2cItem *item, bool is_ack) { uint8_t data = 0; uint32_t i; drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Input_Floating); kit_time_dly_us(1); for(i = 0; i < 8; i++) { data <<= 1; drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); if(drv_gpio_get_pin_status(item->sda_io) == kGpioStatus_High) { data |= 0x01; } drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low); kit_time_dly_us(item->clk_dly); } drv_gpio_set_pin_mode(item->sda_io, kGpioMode_Output_PP); if(is_ack == true) { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_Low);; } else { drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); } drv_gpio_set_pin_status(item->scl_io, kGpioStatus_High); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->scl_io, kGpioStatus_Low); kit_time_dly_us(item->clk_dly); drv_gpio_set_pin_status(item->sda_io, kGpioStatus_High); return data; } kit_ret_e drv_i2c_sync_write(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len) { uint32_t i; kit_ret_e res = kKit_Ret_Ok; I2cItem *item = &i2c_item[dev]; uint8_t snd_buf[10]; drv_i2c_start(item); snd_buf[0] = dev_addr << 1; snd_buf[1] = reg_addr; kit_copy_buf(&snd_buf[2], buf, len); len += 2; for(i = 0; i < len; i++) { res = i2c_sync_write_byte(item, snd_buf[i]); if(res != kKit_Ret_Ok) { break; } } drv_i2c_stop(item); return res; } kit_ret_e drv_i2c_sync_read(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len) { uint32_t i; kit_ret_e res = kKit_Ret_TimeOut; I2cItem *item = &i2c_item[dev]; drv_i2c_start(item); if((i2c_sync_write_byte(item, dev_addr << 1) == kKit_Ret_Ok) && (i2c_sync_write_byte(item, reg_addr) == kKit_Ret_Ok)) { // drv_i2c_stop(item); // kit_time_dly_us(2); drv_i2c_start(item); if(i2c_sync_write_byte(item, dev_addr << 1 | 0x01) == kKit_Ret_Ok) { for(i = 0; i < len; i++) { buf[i] = i2c_sync_read_byte(item, (i != (len - 1))); } res = kKit_Ret_Ok; } } drv_i2c_stop(item); return res; } kit_ret_e drv_i2c_sync_write_then_read(I2cDev dev, uint8_t dev_addr, uint8_t *tx_buf, uint16_t tx_len, uint8_t *rx_buf, uint16_t rx_len) { uint32_t i; kit_ret_e res = kKit_Ret_Ok; I2cItem *item = &i2c_item[dev]; drv_i2c_start(item); res |= i2c_sync_write_byte(item, dev_addr << 1); for(i = 0; i < tx_len; i++) { res |= i2c_sync_write_byte(item, tx_buf[i]); } if(res == kKit_Ret_Ok) { drv_i2c_start(item); res = i2c_sync_write_byte(item, dev_addr << 1 | 0x01); if(res == kKit_Ret_Ok) { for(i = 0; i < rx_len; i++) { rx_buf[i] = i2c_sync_read_byte(item, (i != (rx_len - 1))); } } } drv_i2c_stop(item); return res; } kit_ret_e drv_i2c_sync_direct_read(I2cDev dev, uint8_t dev_addr, uint8_t reg_addr, uint8_t *buf, uint16_t len) { uint32_t i; I2cItem *item = &i2c_item[dev]; kit_ret_e res = kKit_Ret_TimeOut; drv_i2c_start(item); if(i2c_sync_write_byte(item, dev_addr << 1 | 0x01) == true) { for(i = 0; i < len; i++) { buf[i] = i2c_sync_read_byte(item, (i != (len - 1))); } res = kKit_Ret_Ok; } drv_i2c_stop(item); return res; }