i2c - gpio
处理器只支持3个i2c通道,常常会不够用,最近写了一个gpio模拟i2c的driver,把模拟的i2c通道加入了i2c-core中,作为第 4 通道,调用接口与标准i2c一致,代码如下:[cpp]
#define DELAY 2
#define SCL_GPIO GPIO_I2C_SCL
#define SDA_GPIO GPIO_I2C_SDA
static inline void i2c_delay(uint16_t delay)
{
udelay(delay);
}
static inline void set_scl_low(void)
{
gpio_direction_output(SCL_GPIO, 0);
}
static inline void set_scl_high(void)
{
gpio_direction_output(SCL_GPIO, 1);
}
static inline void set_sda_low(void)
{
gpio_direction_output(SDA_GPIO, 0);
}
static inline void set_sda_high(void)
{
gpio_direction_output(SDA_GPIO, 1);
}
static inline void set_sda_in(void)
{
gpio_direction_input(SDA_GPIO);
}
static inline uint8_t get_sda_bit(void)
{
return __gpio_get_value(SDA_GPIO);
}
int i2c_gpio_init(void)
{
int err;
err = gpio_request(SCL_GPIO, NULL);
if (err != 0)
return err;
err = gpio_request(SDA_GPIO, NULL);
set_sda_high();
set_scl_high();
return err;
}
void i2c_gpio_free(void)
{
gpio_free(SDA_GPIO);
gpio_free(SCL_GPIO);
}
static inline void i2c_start(void)
{
set_sda_high();
i2c_delay(DELAY);
set_scl_high();
i2c_delay(DELAY);
set_sda_low();
i2c_delay(DELAY);
set_scl_low();
i2c_delay(DELAY);
}
static inline void i2c_stop(void)
{
set_sda_low();
i2c_delay(DELAY);
set_scl_high();
i2c_delay(4*DELAY);
set_sda_high();
i2c_delay(4*DELAY);
}
/*
* return value:
* 0 --- 收到ACK
* 1 --- 没收到ACK
*/
uint8_t i2c_send_byte(uint8_t send_byte)
{
uint8_t rc = 0;
uint8_t out_mask = 0x80;
uint8_t count = 8;
uint8_t value;
while(count > 0) {
set_scl_low();
i2c_delay(DELAY);
value = ((send_byte & out_mask) ? 1 : 0);
if(value == 1) {
set_sda_high();
} else {
set_sda_low();
}
send_byte <<= 1;
i2c_delay(DELAY);
set_scl_high();
i2c_delay(DELAY);
count--;
}
set_scl_low();
set_sda_in();
i2c_delay(4*DELAY);
set_scl_high();
i2c_delay(DELAY);
rc = get_sda_bit();
i2c_delay(DELAY);
set_scl_low();
return rc;
}
/*
* ack = 0 发送ACK
* ack = 1 发送非ACK停止读取
*/
void i2c_read_byte(uint8_t *buffer, uint8_t ack)
{
uint8_t count = 0x08;
uint8_t data = 0x00;
uint8_t temp = 0;
while(count > 0) {
set_scl_low();
i2c_delay(2*DELAY);
if(count == 8)
set_sda_in();
i2c_delay(DELAY);
set_scl_high();
i2c_delay(2*DELAY);
temp = get_sda_bit();
data <<= 1;
if(temp)
data |= 0x01;
i2c_delay(DELAY);
count--;
}
set_scl_low();
i2c_delay(2*DELAY);
if(ack) {
set_sda_high();
} else {
set_sda_low();
}
i2c_delay(DELAY);
set_scl_high();
i2c_delay(2*DELAY);
*buffer = data;
set_scl_low();
}
struct atxx_i2c_gpio {
struct i2c_adapter adap;
struct device *dev;
struct clk *clk;
struct i2c_msg *msg;
spinlock_t lock;
};
static int send_i2c(struct atxx_i2c_gpio *i2c)
{
int i;
uint8_t ack;
spin_lock_irq(&i2c->lock);
i2c_start();
ack = i2c_send_byte((i2c->msg->addr << 1) | 0x00);
if(ack){
goto out;
}
for(i = 0; i < i2c->msg->len; i++) {&
补充:软件开发 , C++ ,