






















I2C(Inter-Integrated Circuit)总线是由Philips公司开发的一种两线式串行总线,用于连接微处理器及其外围设备。以简单、高效特点著名,占用PCB空间很小,芯片引脚数量少,设计成本低。
总线即意味着可连接多个设备。控制数据传输和时钟频率的设备称为主控,其余为从设备。I2C设备支持多主控模式,但任意时刻只能有一个主控。
组成I2C总线的两个信号线分别为SCL(时钟)和SDA(数据线)。为避免总线信号混乱,从硬件设计角度出发,总线上会外接上拉电阻,默认使SCL和SDA均保持高电平,同时要求各设备连接到总线的输出端必须为OC门(CMOS开漏输出或TTL集电极开路输出),实现“线与”逻辑,即任意设备输出低电平时,都会拉低总线电平。

I2C设备上的串行数据线SDA的接口电路是双向的,输出电路用于向总线上发数据,输入电路用于接收总线上的数据。同样的,串行时钟线SCL也是双向的,对于主机设备而言,通过SCL输出电路发送时钟信号,并检测总线上的SCL电平以决定什么时候发送下一个时钟脉冲;作为从机设备,需要按总线上SCL的信号发送或者接收SDA上的信号,也可以向SCL线发出低电平信号以延长总线时钟信号周期。简而言之,I2C设备的通信频率是主机的SCL脉冲信号决定的,从机需要按照此频率来接收和发送SDA数据
那么,数据到底如何传输呢?
和串口协议一样,I2C也有自己的起始位与停止位。当SCL稳定在高电平时,SDA由高到低的变化将产生一个开始位,而由低到高的变化则产 生一个停止位,均由主设备产生。

I2C设备是以字节为单位进行传输的。当SCL脉冲电平恒为高时,SDA线电平即为传输的有效数据(高电平采样)。每个字节传完后,主设备会放开SDA线,相应的从设备需要拉低SDA线电平,表示收到数据,主设备会检测SDA线电平,以判断传输是否在正常进行(缺确认完成ACK)。

以数据读写为例:在正式开始传输数据之前,I2C主设备需要确定想要和哪个从设备通信(从设备编号),以及是去读数据还是写数据(读写标志),读/写到从设备哪里(寄存器地址),这些信息都需要在开始位后首先确定。

首字节为7位设备地址+1位读写标志,第二字节的8位为寄存器的地址。与写数据不同的是,读数据需要先发送一个写数据帧,从设备确认应答后,需要重新开始一次数据传输,这次就无需重新指定寄存器的地址了,因为寄存器地址已被I2C控制器保存(实际上是一个指针)。
i2c速率
i2c总线在不同模式下具有不同的传输速率上限:

I2C系统的体系结构如图所示,可按5个层级划分,介绍如下:
其中,i2c驱动主要关注i2c核心、i2c总线、i2c设备驱动。

i2c驱动的软件框架与基本的注册流程如上图,说明如下:
面对如此复杂的Linux i2c子系统,驱动工程师要完成哪些工作?
一方面,适配器驱动可能是Linux内核本身还不包含的;另一方面,挂接在适配器上的具体设备驱动可能也是Linux内核还不包含的。因此,工程师要实现的主要工作如下。
i2ctool是一个非常具有实用性的工具,一般系统内都有集成,对于调试非常方便

使用过程中会用到以下参数:
-y:自动选择yes,跳过交互
-r:快速读指令
-q:快速写指令
-f:强制使用此设备地址
i2cdetect -l 探测所有的i2c总线

i2cdetect -y -r <id> 检测某个总线上的i2c设备,注意:这里检测出的是7位地址,不包括读写位

表示0x1e处有设备,若显示UU,则表示该设备已被驱动占用
i2cdetect -F <id> 查看总线设备支持的功能

i2cdump -f -y <id> <device addr> 打印i2c设备所有寄存器的值

i2cget -f -y <id> <device addr> <register addr> 读取某个设备某个寄存器的值
如:i2cget -f -y 1 0x62 0x00 意为读取1号总线上0x62处设备的0x00寄存器的值
i2cset -f -y <id> <device addr> <register addr> <value> 写入某个设备某个寄存器的值
读取/写入多字节寄存器地址,是i2cget和i2cset的升级版,语法如下:
i2ctransfer [-f] [-y] [-v] [-a] <bus id> w-n@<device addr> data-0 data-1 ... data-n r-num
i2ctransfer [-f] [-y] [-v] [-a] <bus id> w-n@<device addr> data-0 data-1 ... data-n
参数说明:
-a:允许使用0x00~0x07和0x78~0x7f地址
w-n:写n个字节
data-0,data-1...,data-n:寄存器地址(读) / 寄存器地址和写的数据(写)
r-num:读n个字节
举例:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。