#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;
}