龙华网站建设营销推广,广东东莞区号,随州哪里学做网站,大学生创业50个小案例前言#xff1a; I2C#xff08;Inter-Integrated Circuit BUS#xff09;是集成电路总线#xff0c;是目前应用最广泛的总线之一#xff0c;最初由PHILIPS#xff08;现为NXP#xff09;设计。它使用多主从架构#xff0c;主要用于连接低速周边设备。I2C总线在硬件物理… 前言 I2CInter-Integrated Circuit BUS是集成电路总线是目前应用最广泛的总线之一最初由PHILIPS现为NXP设计。它使用多主从架构主要用于连接低速周边设备。I2C总线在硬件物理层包括两条线一条数据线SDA和一条时钟线SCL。所有设备都连接在这两条线上。I2C协议在物理层之上添加了协议层定义了通信的规则和过程。I2C通信过程可以类比为体育老师和学生之间的球类传递。老师主设备可以将球数据发送给学生从设备也可以从学生那里接收球。在接收到球后学生应该向老师作出回应。这个过程可以对应到I2C通信中的数据传输和应答过程。I2C总线在传输数据时需要主设备发送时钟信号从设备在每个时钟脉冲的上升沿或下降沿发送或接收一位数据。 一、I2C 硬件框架 在一个芯片(SoC)内部有一个或多个 I2C 控制器 在一个 I2C 控制器上可以连接一个或多个 I2C 设备 I2C 总线只需要 2 条线时钟线 SCL、数据线 SDA 在 I2C 总线的 SCL、SDA 线上都有上拉电阻 二、I2C 软件框架 以 I2C 接口的存储设备 AT24C02 为例
APP 提出要求把字符串www.100ask.net写入 AT24C02 地址 16 开始的 地方 它是大爷不关心底层实现的细节 它只需要调用设备驱动程序提供的接口
AT24C02 驱动 它知道 AT24C02 要求的地址、数据格式 它知道发出什么信号才能让 AT24C02 执行擦除、烧写工作 它知道怎么判断数据是否烧写成功 它构造好一系列的数据发给 I2C 控制器
I2C 控制器驱动 它根据 I2C 协议发出各类信号I2C 设备地址、I2C 存储地址、数据 它根据 I2C 协议判断
三、I2C协议
1.硬件连接 I2C 在硬件上的接法如下所示主控芯片引出两条线 SCL,SDA 线在一条 I2C 总线上可以接很多 I2C 设备我们还会放一个上拉电阻。 2.传输数据类比 怎么通过 I2C 传输数据我们需要把数据从主设备发送到从设备上去也需要把数据从设备传送到主设备上去数据涉及到双向传输。 体育老师可以把球发给学生也可以把球从学生中接过来。 发球 老师开始了(start) 老师A我要发球给你(地址/方向) 学生 A到(回应) 老师把球发出去传输 A 收到球之后应该告诉老师一声回应 老师结束停止 接球 老师开始了(start) 老师B把球发给我(地址/方向) 学生 B到 B 把球发给老师传输 老师收到球之后给 B 说一声表示收到球了回应 老师结束停止 我们就使用这个简单的例子来解释一下 IIC 的传输协议 老师说开始了表示开始信号(start) 老师提醒某个学生要发球表示发送地址和方向(address/read/write) 老师发球/接球表示数据的传输 收到球要回应回应信号(ACK) 老师说结束表示 IIC 传输结束(P) 3. IIC 传输数据的格式 (1)写操作 主芯片要发出一个 start 信号 然后发出一个设备地址(用来确定是往哪一个芯片写数据)方向(读/写0 表示写1 表示读) 从设备回应(用来确定这个设备是否存在)然后就可以传输数据 主设备发送一个字节数据给从设备并等待回应 每传输一字节数据接收方要有一个回应信号确定数据是否接受完成)然后再传输下一个数据。 数据发送完之后主芯片就会发送一个停止信号。 图白色背景表示主→从灰色背景表示从→主 (2)读操作 主芯片要发出一个 start 信号 然后发出一个设备地址(用来确定是往哪一个芯片写数据)方向(读/写0 表示写1 表示读) 从设备回应(用来确定这个设备是否存在)然后就可以传输数据 从设备发送一个字节数据给主设备并等待回应 每传输一字节数据接收方要有一个回应信号确定数据是否接受完成)然后再传输下一个数据。 数据发送完之后主芯片就会发送一个停止信号。 下图白色背景表示主→从灰色背景表示从→主 (3).I2C 信号 I2C 协议中数据传输的单位是字节也就是 8 位。但是要用到 9 个时钟前面 8 个时钟用来传输 8 数据第 9 个时钟用来传输回应信号。传输时先传输最高位(MSB)。 开始信号SSCL 为高电平时SDA 山高电平向低电平跳变开始传送数据。 结束信号PSCL 为高电平时SDA 由低电平向高电平跳变结束传送数据。 响应信号(ACK)接收器在接收到 8 位数据后在第 9 个时钟周期拉低 SDA SDA 上传输的数据必须在 SCL 为高电平期间保持稳定SDA 上的数据只能在 SCL 为低电平期间变化 I2C 协议信号如下 在SCL低电平状态下改变SDA在SCL高电平状态下保持SDA。 (4).协议细节 1) 如何在 SDA 上实现双向传输 主芯片通过一根 SDA 线既可以把数据发给从设备也可以从 SDA 上读取数据连接 SDA 线的引脚里面必然有两个引脚发送引脚/接受引脚。 2) 主、从设备都可以通过 SDA 发送数据肯定不能同时发送数据怎么错开时间 在9 个时钟里 前 8 个时钟由主设备发送数据的话第 9 个时钟就由从设备发送数据。 前 8 个时钟由从设备发送数据的话第 9 个时钟就由主设备发送数据。 3) 双方设备中某个设备发送数据时另一方怎样才能不影响 SDA 上的数据 设备的 SDA 中有一个三极管使用开极/开漏电路(三极管是开极CMOS 管是开漏作用一样)。如果主机发送1从机因为某些错误发送了0则会出现短路的状况容易烧起来。 这里我们就需要运用到规范钟 外加一个上拉电阻有效的避免了短路烧毁电路情况的发生。 当某一个芯片不想影响 SDA 线时那就不驱动这个三极管 想让 SDA 输出高电平双方都不驱动三极管(SDA 通过上拉电阻变为高电平) 想让 SDA 输出低电平就驱动三极管 例子 主设备发送8bit给从设备 前 8 个 clk 从设备不要影响 SDA从设备不驱动三极管 主设备决定数据主设备要发送 1 时不驱动三极管要发送 0 时驱动三极管 第 9 个 clk由从设备决定数据 主设备不驱动三极管 从设备决定数据要发出回应信号的话就驱动三极管让 SDA 变为 0 为何 SCL 也要使用上拉电阻 在第 9 个时钟之后如果有某一方需要更多的 时间来处理数据它可以一直驱动三极管把 SCL 拉低。 当 SCL 为低电平时候大家都不应该使用 IIC 总线只有当 SCL 从低电平变为高电平的时候IIC 总线才能被使用。 当它就绪后就可以不再驱动三极管这是上拉电阻把 SCL 变为高电平其 他设备就可以继续使用 I2C 总线了。 四、SMBus 协议
1. SMBus 是 I2C 协议的一个子集 SMBus: System Management Bus系统管理总线。 SMBus 最初的目的是为智能电池、充电电池、其他微控制器之间的通信链路而定义的。 SMBus 也被用来连接各种设备包括电源相关设备系统传感器EEPROM 通讯 设备等等。 SMBus 为系统和电源管理这样的任务提供了一条控制总线使用 SMBus 的系统设备之间发送和接收消息都是通过 SMBus而不是使用单独的控制线这样可以节省设备的管脚数。 SMBus 是基于 I2C 协议的SMBus 要求更严格SMBus 是 I2C 协议的子集。 SMBus 有哪些更严格的要求跟一般的 I2C 协议有哪些差别 VDD 的极限值不一样 I2C 协议范围很广甚至讨论了高达 12V 的情况 SMBus1.8V~5V 最小时钟频率、最大的 Clock Stretching Clock Stretching 含义某个设备需要更多时间进行内部的处理时 它可以把 SCL 拉低占住 I2C 总线,也可以叫做时钟延长。 I2C 协议时钟频率最小值无限制Clock Stretching 时长也没有 限制 SMBus时钟频率最小值是 10KHzClock Stretching 的最大时间值 也有限制 地址回应(Address Acknowledge) 一个 I2C 设备接收到它的设备地址后 是否必须发出回应信号 I2C 协议没有强制要求必须发出回应信号 SMBus强制要求必须发出回应信号这样对方才知道该设备的状态 busyfailed或是被移除了 SMBus 协议明确了数据的传输格式 I2C 协议它只定义了怎么传输数据但是并没有定义数据的格式这完全由设备来定义 SMBus定义了几种数据格式(后面分析) REPEATED START Condition(重复发出 S 信号) 比如读 EEPROM 时涉及 2 个操作 1把存储地址发给设备 2读数据 在写、读之间可以不发出 P 信号而是直接发出 S 信号这个 S 信号就是 REPEATED START如图所示 SMBus Low Power VersionSMBus 也有低功耗的版本 2.SMBus 协议分析 对于 I2C 协议它只定义了怎么传输数据但是并没有定义数据的格式 这完全由设备来定义。 对于 SMBus 协议它定义了几种数据格式。
注意下面文档中的 Functionality flag 是 Linux 的某个 I2C 控制器驱动所支持的功能。比如 Functionality flag: I2C_FUNC_SMBUS_QUICK表示需要 I2C 控制器支持 SMBus Quick Command。
1symbols(符号)
S (1 bit) : Start bit(开始位)
Sr (1 bit) : 重复的开始位
P (1 bit) : Stop bit(停止位)
R/W# (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.(读写位)
A, N (1 bit) : Accept and reverse accept bit.(回应位)
Address(7 bits): I2C 7 bit address. Note that this can be expanded as usual toget a 10 bit I2C address.(地址位7 位地址)
Command Code (8 bits): Command byte, a data byte which often selects a register onthe device.(命令字节一般用来选择芯片内部的寄存器)
Data Byte (8 bits): A plain data byte. Sometimes, I write DataLow, DataHighfor 16 bit data.(数据字节8 位如果是 16 位数据的话用 2 个字节来表示DataLow、DataHigh)
Count (8 bits): A data byte containing the length of a block operation.(在 block 操作总表示数据长度)
[..]: Data sent by I2C device, as opposed to data sent by the hostadapter.(中括号表示 I2C 设备发送的数据没有中括号表示 host adapter 发送的数据)
2SMBus Quick Command 只是用来发送一位数据R/W#本意是用来表示读或写但是在 SMBus 里可以用来表示其他含义。比如某些开关设备可以根据这一位来决定是打开还是关闭。
Functionality flag: I2C_FUNC_SMBUS_QUICK
3SMBus Receive Byte I2C-tools 中的函数i2c_smbus_read_byte()。读取一个字节Host adapter 接收到一个字节后不需要发出回应信号(上图中 N 表示不回应)。
Functionality flag: I2C_FUNC_SMBUS_READ_BYTE4SMBus Send Byte I2C-tools 中的函数i2c_smbus_write_byte()。发送一个字节。
Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE
5SMBus Read Byte I2C-tools 中的函数i2c_smbus_read_byte_data()。先发出Command Code(它一般表示芯片内部的寄存器地址)再读取一个字节的数据。上面介绍的 SMBus Receive Byte 是不发送 Comand直接读取数据。
Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA
6SMBus Read Word I2C-tools 中的函数i2c_smbus_read_word_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再读取 2 个字节的数据。
Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA 7SMBus Write Byte I2C-tools 中的函数i2c_smbus_write_byte_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发出 1 个字节的数据。
Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA
8SMBus Write Word I2C-tools 中的函数i2c_smbus_write_word_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发出 1 个字节的数据。
Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA
9SMBus Block Read I2C-tools 中的函数i2c_smbus_read_block_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发起度操作 先读到一个字节(Block Count)表示后续要读的字节数 然后读取全部数据
Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA
10SMBus Block Write I2C-tools 中的函数i2c_smbus_write_block_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发出 1 个字节的 Byte Conut(表 示后续要发出的数据字节数)最后发出全部数据。
Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
11I2C Block Read 在一般的 I2C 协议中也可以连续读出多个字节。它跟 SMBus Block Read 的差别在于设备发出的第 1 个数据不是长度 N如下图所示 I2C-tools 中的函数i2c_smbus_read_i2c_block_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发出 1 个字节的 Byte Conut(表示后续要发出的数据字节数)最后发出全部数据。
Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK
12I2C Block Write 在一般的 I2C 协议中也可以连续发出多个字节。它跟 SMBus Block Write 的差别在于发出的第 1 个数据不是长度 N如下图所示 I2C-tools 中的函数i2c_smbus_write_i2c_block_data()。先发出 Command Code(它一般表示芯片内部的寄存器地址)再发出 1 个字节的 Byte Conut(表示后续要发出的数据字节数)最后发出全部数据。
Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
13SMBus Block Write - Block Read Process Call 先写一块数据再读一块数据。
Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL
14Packet Error Checking (PEC) PEC 是一种错误校验码如果使用 PEC那么在 P 信号之前数据发送方要 发送一个字节的 PEC 码(它是 CRC-8 码)。以 SMBus Send Byte 为例下图中一个未使用 PEC另一个使用 PEC 3.SMBus 和 I2C 的建议 因为很多设备都实现了 SMBus而不是更宽泛的 I2C 协议所以优先使用 SMBus。即使 I2C 控制器没有实现 SMBus软件方面也是可以使用 I2C 协议来模拟 SMBus。所以Linux 建议优先使用 SMBus。