当前位置:编程学习 > C/C++ >>

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++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,