GPIO模拟i2c时序



#define DELAY   1

/******************************start*****************************************/
void i2c_start(void)
{
    gpio_direction_output(SDA, 1);
    gpio_direction_output(SCL, 1);
    udelay(DELAY);

    gpio_set_value(SDA, 0);
    udelay(DELAY);
            
    gpio_set_value(SCL, 0);
    udelay(DELAY);  
}

/**********************************************stop****************************************/
void i2c_stop(void)
{
    gpio_set_value(SCL, 0);  
    gpio_set_value(SDA, 0);
    udelay(DELAY);  

    gpio_set_value(SCL, 1);  
    udelay(DELAY);
    gpio_set_value(SDA, 1);  
    udelay(DELAY);
}  

/********************************send_ack****************************************/
void i2c_send_ack(u8 ack)
{
    if(ack)
        gpio_direction_output(SDA, 1);
    else
        gpio_direction_output(SDA, 0);
    udelay(DELAY);

    gpio_set_value(SCL, 1);  
    udelay(DELAY);
      
    gpio_set_value(SCL, 0);  
    udelay(DELAY);
}  

/********************************receive_ack*********************************/
u8 i2c_receive_ack(void)  
{  
    u8 rc = 0;
      
    gpio_direction_input(SDA);  
    gpio_set_value(SCL, 1);
    udelay(DELAY);  
      
    if(gpio_get_value(SDA)) {
        rc = 1;  
    }  
    gpio_set_value(SCL, 0);
    gpio_direction_output(SDA, 1);                
    return rc;  
}

/********************************send****************************************/
u8 i2c_send_byte(u8 send_byte)  
{  
    u8 rc = 0;  
    u8 out_mask = 0x80;
    u8 value;  
    u8 count = 8;  
    while(count > 0) {                  
        value = ((send_byte & out_mask) ? 1 : 0);     
        if (value == 1) {                                     
            gpio_set_value(SDA, 1);       
        }
        else {                                    
            gpio_set_value(SDA, 0);  
        }      
        udelay(DELAY);  

        gpio_set_value(SCL, 1);
        udelay(DELAY);  
                       
        gpio_set_value(SCL, 0);
        udelay(DELAY);  
                    
        out_mask >>= 1;        
        count--;         
    }  
      
    gpio_set_value(SDA, 1);    
    rc = i2c_receive_ack();
    return rc;  
}  

/**********************************************receive*************************************/
void i2c_read_byte(u8 *buffer, u8 ack)  
{  
    u8 count = 0x08;  
    u8 data = 0x00;  
    u8 temp = 0;  

    gpio_direction_input(SDA);   
    while(count > 0) {
        gpio_set_value(SCL, 1);  
        udelay(DELAY);  
        temp = gpio_get_value(SDA);       
        data <<= 1;  
        if (temp)  
            data |= 0x01;  
        gpio_set_value(SCL, 0);  
        udelay(DELAY);  
        count--;  
    }  
    i2c_send_ack(ack);//0 = ACK    1 = NACK   
    *buffer = data;
}  

//向client的某个寄存器写入多个字节,len是要写入的数据的长度   
/***********************************************write_bytes********************************/
u8 i2c_write(u8 device_id, u8 reg_address, u8* data, u8 len)
{
    u8 rc = 0;
    u8 i;
    i2c_start();
      
    rc |= i2c_send_byte( (device_id << 1) | 0x00 );  
    rc |= i2c_send_byte(reg_address);
    if(data==NULL ||0==len) {
        i2c_stop();  
        return rc;  
    }
          
    for(i=0; i<len; i++) {
        rc |= i2c_send_byte(*data);  
        data++;  
    }

    i2c_stop();

    return rc;
}

//从某个register中读取len个字节放在长度为len的缓冲区buffer中   
/***********************************************read_bytes********************************/
u8 i2c_read(u8 device_id, u8 reg_address, u8 *buffer, u16 len)
{
    u8 rc = 0;
    u16 i;  

    i2c_start();
    rc |= i2c_send_byte( (device_id << 1) | 0x00 );
    rc |= i2c_send_byte(reg_address);  
    i2c_start();//restart I2C      
    rc |= i2c_send_byte( (device_id << 1) | 0x01 );

    for(i=0;i<len;i++) {  
        i2c_read_byte(buffer++, !(len-i-1));//  !(len-i-1)  这个用来保证在读到每个字节后发送一个ACK并能在最后一个字节读完后发送一个NACK
    }

    i2c_stop();   

    return rc;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值