i2c总线之通信原理及linux驱动中读写时序的实现

您所在的位置:网站首页 I2C通讯原理图 i2c总线之通信原理及linux驱动中读写时序的实现

i2c总线之通信原理及linux驱动中读写时序的实现

2024-07-14 18:04| 来源: 网络整理| 查看: 265

一、I2C简介 I2C使用两条线在主控制器和从机之间通信,SCL(串行时钟线)和SDA(串行数据线),这两条线需接5~10欧上拉电阻,总线空闲空闲时,SCL和SDA处于高电平,I2C总线标准模式速度可以达到100K/S,快速模式可以达到400K/S。 一个I2C总线可以挂多个I2C从设备,通过I2C器件地址去识别不同的设备,如图 在这里插入图片描述 二、I2C通信原理 1.起始位 在这里插入图片描述 2.停止位 在这里插入图片描述 3.数据传输:I2C在数据传输时要保证SCL高电平期间,SDA数据稳定,因此SDA上数据变化只能SCL低电平期间发生,如图 在这里插入图片描述 4.应答信号:当I2C主机发送完8位数据后,将SDA设置为输入状态,等待I2C从机应答,应答信号由从机发出,主机需要提供应答信号所需时钟,主机发送完8位数据后,紧跟一个时钟信号,就是给应答信号提供的,从机将SDA拉低来表示发出应答信号,表示通信成功,否则表示通信失败,I2C总线是单字节读写时序 5.I2C写时序 在这里插入图片描述 在这里插入图片描述

开始信号发送 I2C 设备地址,每个 I2C 器件都有一个设备地址,通过发送具体的设备地址来决定访问哪个I2C 器件。这是一个8位的数据,其中高7位是设备地址,最后1位是读写位,为1的话表示这是一个读操作,为0的话表示这是一个写操作。I2C 器件地址后面跟着一个读写位,为0表示写操作,为1表示读操作。从机发送的 ACK 应答信号。重新发送开始信号。发送要写写入数据的寄存器地址。从机发送的 ACK 应答信号。发送要写入寄存器的数据从机发送的 ACK 应答信号。停止信号。

6.I2C读时序:读时序分为4大步,第一步是发送设备地址,第二步是发送要读取的寄存器地址,第三步重新发送设备地址,最后一步就是I2C从器件输出要读取的寄存器值 在这里插入图片描述 在这里插入图片描述

主机发送起始信号。主机发送要读取的I2C从设备地址。读写控制位,因为是向I2C从设备发送数据,因此是写信号0。从机发送的ACK应答信号。重新发送START信号。主机发送要读取的寄存器地址。从机发送的ACK应答信号。重新发送START信号。重新发送要读取的I2C从设备地址。读写控制位,这里是读信号1,表示接下来是从I2C从设备里面读取数据。从机发送的ACK应答信号。从 I2C 器件里面读取到的数据。主机发出NO ACK信号,表示读取完成,不需要从机再发送ACK信号了。主机发出STOP信号,停止I2C通信

三、代码实现I2C读写时序

#include static int i2c_write(struct i2c_adapter *i2c_adap,unsigned int address, unsigned int len, unsigned char const *data) { struct i2c_msg msgs[1]; int ret; if(!data || !i2c_adap){ printk("---error--- "); } msgs[0].addr=address; msgs[0].flags=0; //write flag msgs[0].buf=(unsigned char *)data; msgs[0].len=len; /*i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) num:消息数量,也就是 msgs 的数量 返回值:负值,失败,其他非负值,发送的 msgs 数量*/ ret=i2c_transfer(i2c_adap,msgs,1); if (ret == 1) return 0; else if(ret == 0) return -EBUSY; else return ret; } static int i2c_read(struct i2c_adapter *i2c_adap, unsigned int address, unsigned int reg, unsigned int len, unsigned char *data) { struct i2c_msg msgs[2]; int ret; if(!data || !i2c_adap){ printk("---error--- "); } //发送要读取的寄存器首地址 msgs[0].addr=address; msgs[0].flags=0; //write flag msgs[0].buf=® //读取的首地址 msgs[0].len=1; //读取寄存器数据 msgs[1].addr=address; msgs[1].flags=I2C_M_RD; //read flag msgs[1].buf=data; msgs[1].len=len; //读取的数据长度 ret=i2c_transfer(i2c_adap,msgs,2); if (ret == 2) return 0; else if(ret == 0) return -EBUSY; else return ret; }

在学习中进步,如有错误,请多多批评指正



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3