GPIO模拟的I2C操作

嗯,是我写的,已经在上市产品中验证没有错误。呵呵

后来有一天我才知道,原来新的kernel中已经提供了一种通过两个gpio口调用i2c-core的机制,而且还能在这两个gpio口挂载多个设备,用起来就像真的i2c总线一样。所以以后我们都应该用kernel中的这种机制!毕竟自己写的模拟代码不是很可靠的,而且不方便挂载多个设备(当然,你可以通过复杂的逻辑和方法去实现,但是这不值得,除非你是本着学习的目的)

不过这个自己写的gpio模拟i2c的代码通过对gpio的不停的拉高拉低来模拟scl和sda线的动作可以让我们对i2c的操作和协议认识的更清楚。因此对于初学者来说还是有一较大价值的。其实,从经验上讲,每一个刚刚接触到嵌入式的同学都应该能够自己独立完成一个这样的模拟操作!这样你会提高的很快!

 

代码如下:

这不是完整的代码,仅仅提供模拟操作部分供大家参考。

 

/****I2C*****I2C*****I2C*****I2C*****I2C*****I2C*****I2C*****I2C*****I2C*****I2C*****I2C****/ #define DELAY 1 #define SCL 89 #define SDA 20 #define RST 19 #define IRQ 108 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); } 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); } 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); } 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; } 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; } 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是要写入的数据的长度 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

 

 

你可能感兴趣的:(I2C)