I2C总线相关_4

时间:2022-11-12 19:14:29

I2C会话分为两种
一种是读会话,一种是写会话
这两种会话都有固定的格式,按照数据手册上的时序写就行了

下面提供的是标准的I2C时序

特别注意下面的DELAY(x) 宏,你可以定义为你需要的时间.

时间可以从芯片手册中得知.

注意:I2C可以由内核中I2C框架实现,也可以用GPIO模拟I2C来实现.
两者的切换需要配置复用寄存器

//写会话
EXPORT_SYMBOL(gpio_i2c_write);
void gpio_i2c_write(unsigned char devaddress, unsigned char address, unsigned char data)
{
    i2c_start_bit();
    i2c_send_byte(devaddress);
    i2c_receive_ack();
    i2c_send_byte(address);
    i2c_receive_ack();
    i2c_send_byte(data); 
    i2c_receive_ack();
    i2c_stop_bit();
}

//这是标准i2c的流程

/* * sends a start bit via I2C rountine. * */
static void i2c_start_bit(void)
{
        DELAY(1);
        i2c_set(SDA | SCL);
        DELAY(1);
        i2c_clr(SDA);
        DELAY(1);
}

//一般起始位都是在SDA与SCL同时高的时候,拉低SDA,这就开始了.
/* * sends a character over I2C rountine. * * @param c: character to send * */
static void i2c_send_byte(unsigned char c)
{
    int i;
    local_irq_disable();
    for (i=0; i<8; i++)
    {
        DELAY(1);
        i2c_clr(SCL);
        DELAY(1);
        if (c & (1<<(7-i)))
            i2c_set(SDA);
        else
            i2c_clr(SDA);
        DELAY(1);
        i2c_set(SCL);
        DELAY(1);
        i2c_clr(SCL);
    }
    DELAY(1);                                  
    local_irq_enable();
}
//一般发送字节,要不是发送的地址,就是发送的数据,起始都是一样的,都是将字节的字节发送,从最高位到最低位.
/* receives an acknowledge from I2C rountine. * * @return value: 0--Ack received; 1--Nack received * */                                
static int i2c_receive_ack(void)
{
    int nack;
    unsigned char regvalue;

    DELAY(1);

    regvalue = HW_REG(GPIO_0_DIR);
    regvalue &= (~SDA);
    HW_REG(GPIO_0_DIR) = regvalue;

    DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
    i2c_set(SCL);
    DELAY(1);
    nack = i2c_data_read();

    DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
  // i2c_set(SDA);
  // DELAY(1);
    if (nack == 0)
        return 1; 

    return 0;
}
//在往总线上发送一个字节之后,从机设备会发回一个ack,也就是回应,我们需要捕获这个回应.然后鉴别是否正确
/* * sends a stop bit via I2C rountine. * */
static void i2c_stop_bit(void)
{
        /* clock the ack */
        DELAY(1);
        i2c_set(SCL);
        DELAY(1);
        i2c_clr(SCL);

        /* actual stop bit */                                                                                                             
        DELAY(1);
        i2c_clr(SDA);
        DELAY(1);
        i2c_set(SCL);
        DELAY(1);
        i2c_set(SDA);
        DELAY(1);
}
//停止位,一般是在SDA和SCL同时为高的时候拉低SDA,然后代表依次会话结束.

//读会话
EXPORT_SYMBOL(gpio_i2c_read);
unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
{
    int rxdata;

    i2c_start_bit();
    i2c_send_byte(devaddress);
    i2c_receive_ack();
    i2c_send_byte(address);
    i2c_receive_ack();   
    i2c_start_bit();
    i2c_send_byte((unsigned char)(devaddress) | 1);
    i2c_receive_ack();
    rxdata = i2c_receive_byte();
    i2c_send_ack();//注意,这里是读ack
    i2c_stop_bit();
    return rxdata;
}
//读的周期一般比较长.