用GPIO模拟I2C操作


#define OUTP 1                          //表示GPIO接口方向为输出  
#define INP  0                           //表示GPIO接口方向为输入  

#define DELAY_TIME      24

#define I2C_SET_DIR(p, v)   do{if(v){IO0DIR=IO0DIR|(p);}else{IO0DIR=IO0DIR&(~(p));}}while(0)
#define I2C_SET_VAL(p, v)   do{if(v){IO0SET=(p);}else{IO0CLR=(p);}}while(0)
#define I2C_GET_VAL(p)      ((IO0PIN&(p)) ? 1 : 0)

#define DELAY()         usleep(DELAY_TIME)
#define DELAY2()         usleep(DELAY_TIME/2)
#define DELAY3()         usleep(DELAY_TIME*2)

extern void usleep(uint32 us);

int i2c_start(void)  
{  
    I2C_SET_DIR(SDA, OUTP);
    I2C_SET_DIR(SCL, OUTP);
    DELAY(); 

    I2C_SET_VAL(SDA, 1);
    I2C_SET_VAL(SCL, 1);
    DELAY();
    I2C_SET_VAL(SDA, 0);
    DELAY2();
    I2C_SET_VAL(SCL, 0);
    DELAY2();   
}  

void i2c_stop(void)  
{  
    I2C_SET_VAL(SCL, 1);  
    I2C_SET_DIR(SDA, OUTP);
    I2C_SET_VAL(SDA, 0);  
    DELAY();  
    I2C_SET_VAL(SDA, 1);             //SCL高电平时,SDA由低变高  
    DELAY(); 
}  


uint8 i2c_read_ack(void)   
{
    uint8 r;  

    //I2C_SET_VAL(SCL,0);
    I2C_SET_DIR(SDA, INP);
    DELAY();
    I2C_SET_VAL(SCL,1);
    DELAY();
    r = I2C_GET_VAL(SDA);
    I2C_SET_VAL(SCL,0);
    DELAY(); 

    return (r?0:1);
}  

void i2c_send_ack(uint8 ack)   
{  
    //I2C_SET_VAL(SCL, 0); 
    I2C_SET_DIR(SDA, OUTP);
    DELAY2();
    I2C_SET_VAL(SDA, (ack ? 0 : 1));
    DELAY2();  
    I2C_SET_VAL(SCL,1);
    DELAY();  
    I2C_SET_VAL(SCL,0);
    DELAY(); 
}

uint8 i2c_write_byte(uint8 b)  
{  
    uint8 i;  

    I2C_SET_DIR(SDA, OUTP);
    for(i=0; i<8; i++)
    {
        DELAY2();
        I2C_SET_VAL(SDA, (b&0x80));
        DELAY2();
        I2C_SET_VAL(SCL, 1);
        DELAY();
        I2C_SET_VAL(SCL, 0);
        b<<=1;
    }
    //  DELAY2();
    return i2c_read_ack();
}


uint8 i2c_read_byte(uint8 ack)   
{  
    uint8 i, r = 0;  

    I2C_SET_DIR(SDA, INP);
    for(i=0; i<8; i++)
    {
        DELAY();
        I2C_SET_VAL(SCL, 1);
        r = (r <<1) | I2C_GET_VAL(SDA);
        DELAY();  
        I2C_SET_VAL(SCL, 0);
    }
    DELAY2();  
    i2c_send_ack(ack);
    return r;  
}  

uint8 i2c_read(uint8 addr, uint8* buf, int len)  
{  
    uint8 i;  
    addr = (addr<<1) | 1;

    i2c_start();
    if(!i2c_write_byte(addr))
        goto _err;

    for (i=0; i<len; i++)
    {
        DELAY3();
        buf[i] = i2c_read_byte((i!=(len-1))?1:0);  
    }

    i2c_stop();
    return len;

_err:
    i2c_stop();
    return 0;   
}

uint8 i2c_write (uint8 addr, uint8* buf, int len)  
{  
    uint8 n;
    uint8 i;
    addr = (addr << 1);

    i2c_start();
    if(!i2c_write_byte(addr))           //no ack
        goto _err;

    for (i=0; i<len; i++)
    {
        DELAY3();
        if(!i2c_write_byte(buf[i]))
            goto _err;
    }

    i2c_stop();
    return len;

_err:
    i2c_stop();
    return 0;   
}


 
 
 

                
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值