Linux GPIO 模拟I2C

来源:互联网 发布:java web相关书籍 编辑:程序博客网 时间:2024/05/07 17:18
I2C速率

NormalSpeed:100Kbps

Fast  Speed:          400Kbps

High  Speed: 3.5Mbps

I2C数据信号


1、  空闲状态

I2C总线空闲时,SDA和SCL两条信号线同时处于高电平。

因此,通常I2C都会有外接上拉电阻,在I2C空闲时,SCL和SDA处于高电平状态。

这里空闲不是指睡眠状态,在睡眠状态SCLSDA是低电平的

2、  启动信号

SCL保持高电平,SDA从高到低变化;


3、  停止信号

SCL保持高电平,SDA从低到高变化;


4、  数据传送

读取SDA电平时,SCL保持高电平

SDA电平变化时,SCL保持低电平


5、  应答信号

应答位,即ACK,I2C总线8位字节传送完成后,有接收器发送一个ACK信号。

即SCL在第9位时,SDA被接收器拉为低电平,发送器读取SDA为低电平时,即应答有效。

每传送一字节都需要应答信号。

I2C数据传送


1、  地址格式

I2C采用7位地址寻址,加上读写标志位。

所以通常slave address = slave chip address << 1;

2、  传送过程

启动信号Slave Address + R/W --> ACK --> Data --> ACK --> Data --> ACK -->*******--> 停止信号

示例代码

 代码:

//设置你自己的要配置的GPIO#define SCLGPIO_SCL#define SDAGPIO_SDA#define DELAY     5/* GPIO 初始化配置 *//* I2C的gpio 如果外部有上拉电阻的话,就配置成None Pull,如果没有上拉电阻,就配置成Pull-UP */void gpio_i2c_init(void){s3c_gpio_cfgpin(SCL, S3C_GPIO_INPUT);s3c_gpio_cfgpin(SDA, S3C_GPIO_INPUT);s3c_gpio_setpull(SCL, S3C_GPIO_PULL_UP);s3c_gpio_setpull(SDA, S3C_GPIO_PULL_UP);s5p_gpio_set_drvstr(SCL, S5P_GPIO_DRVSTR_LV4);s5p_gpio_set_drvstr(SDA, S5P_GPIO_DRVSTR_LV4);}/* 启动信号 */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);}/* 发送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);}/* 接收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;}/* 发送字节 */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;}/* 使用方法*/static int gpio_i2c_read_data(struct i2c_client *client,u16 reg, u8 *values, u16 length){u8 *reg_u8;u8 rc;int i,j;reg_u8 = (u8 *)&reg;printk("gpio_i2c_read_data:length:%d\n",length);gpio_i2c_init();//初始化GPIOi2c_start();//启动信号rc = i2c_send_byte((client->addr << 1) | 0x00);//Slave Address 写数据if(rc) {printk("i2c_send_byte no ack 1\n");return -1;}for(j = 0; j < 2; j++){rc = i2c_send_byte(reg_u8[j]);//发送dataif(rc) {printk("i2c_send_byte no ack 2\n");return -1;}}i2c_stop();//停止信号udelay(200);i2c_start();//启动信号rc = i2c_send_byte( (client->addr << 1) | 0x01 );//发送从机地址 读命令if(rc){printk("i2c_send_byte no ack 3\n");return -1;}for(i = 0; i < length; i++){ i2c_read_byte(values++, !(length - i -1));//读取数据}i2c_stop();//停止信号gpio_i2c_init();return length;}


0 0