I2C介绍
I2C硬件框架
- 一个Soc一般有多个I2C接口,一条I2C总线上,可以挂载一个或多个I2C设备,I2C设备用地址区分。
- I2C总线上,有两条线,一条是SCL时钟线,一条是SDA线,这两条线上都有上拉电阻
I2C软件框架
- App:不关心底层实现细节,只需要调用设备驱动程序提供的接口。
- 芯片驱动:知道芯片要求的地址、数据格式;知道怎么发出信号才能让芯片工作,一些芯片特定的工作状态;构造好数据结构给I2C控制器。
- I2C控制器驱动:根据I2C协议发出各类信号,I2C设备地址、I2C存储地址、数据;根据I2C协议判断数据
I2C协议学习
I2C协议
I2C协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。起始和结束信号总是由主设备产生。
起始和结束信号产生条件:总线在空闲状态时,SCL和SDA都保持着高电平,当SCL为高电平而SDA由高到低的跳变,表示产生一个起始条件;当SCL为高而SDA由低到高的跳变,表示产生一个停止条件。
传输数据流程:数据传输以字节为单位,主设备在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。
主设备在传输有效数据之前需要先指定从设备地址,地址指定过程和上面数据传输过程一样,只不过大多数从设备的地址是7位,协议规定添加一个最低位,用来表示数据传输方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。
向指定设备发送数据的格式,如下图所示,(每一最小包数据由9bit组成,8bit内容+1bit ACK, 如果是地址数据,则8bit包含1bit方向)
主设备往从设备写数据
主设备往从设备读数据
主设备往从设备写数据,重启起始条件,然后往从设备读取数据
SMBUS协议
SMBus最初的目的是为了智能电池、充电电池、其他微控制器之间的通信链路而定义的。
SMBus为系统和电源管理这样的任务提供了一条控制总线,使用SMBus的系统,设备之间发送和接手消息都是通过SMBus,而不是使用单独的控制线,这样可以节省设备管脚数。SMBus是I2C协议的子集。
- Linux内核文档:Documentation\i2c\smbus-protocol.rst
- SMBus协议: http://www.smbus.org/specs/
- 因为很多设备都实现了SMBus,而不是更宽泛的I2C协议,所以优先使用SMBus。 即使I2C控制器没有实现SMBus,软件方面也是可以用I2C协议来模拟SMBus。 所以:Linux建议优先使用SMBus
I2C | SMBus | |
---|---|---|
VDD | 范围很广,0~12v | 1.8V~5V |
最小时钟频率 | 时钟频率最小值无限制 | 时钟频率最小值是10KHz |
最大的Clock Stretching1 | 没有限制 | 有限制 |
地址回应(Address Acknowledge) | 没有强制要求必须发出回应信号 | 强制要求必须发出回应信号2 |
数据的传输格式 | 只定义了如何传输数据,格式由设备定义 | 定义了几种数据格式(后面分析) |
重复发出S信号(REPEATED START Condition) | 需要发送S信号 | 可以不发出P信号,而是直接发出S信号3 |
低功耗版本( Low Power Version) | 无 | 有 |
1. symbol符号
- 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 to get a 10 bit I2C address.(地址位,7位地址)
- Command Code (8 bits): Command byte, a data byte which often selects a register on the device.(命令字节,一般用来选择芯片内部的寄存器)
- Data Byte (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh for 16 bit data.(数据字节,8位;如果是16位数据的话,用2个字节来表示:DataLow、DataHigh)
- Count (8 bits): A data byte containing the length of a block operation.(在block操作中,表示数据长度)
adapter.
(中括号表示I2C设备发送的数据,没有中括号表示host adapter发送的数据)
2. SMBus Quick Command Protocal
只是用来发送一位数据:R/W#本意是用来表示读或写,但是在SMBus里可以用来表示其他含义。 比如某些开关设备,可以根据这一来决定是打开还是关闭。
Functionality flag4: I2C_FUNC_SMBUS_QUICK
3. SMBus Receive Byte
I2C-tools中的函数:i2c_smbus_read_byte(),读取一个字节,Host adapter接收到一个字节后不需要发出回应信号(上图中N表示不回应)。
Functionality flag4: I2C_FUNC_SMBUS_READ_BYTE
4. SMBus Send Byte
I2C-tools中的函数:i2c_smbus_write_byte(), 发送一个字节。
Functionality flag4: I2C_FUNC_SMBUS_WRITE_BYTE
5. SMBus Read Byte
I2C-tools中的函数:i2c_smbus_read_byte_data()。 先发出Command Code(它一般表示芯片内部的寄存器地址),再读取1个字节的数据。 上面介绍的SMBus Receive Byte是不发Comand,直接读取数据。
Functionality flag4: I2C_FUNC_SMBUS_READ_BYTE_DATA
6. SMBus Read Word
I2C-tools中的函数:i2c_smbus_read_word_data()。先发出Command Code(它一般表示芯片内部的寄存器地址),再读取2个字节的数据。
Functionality flag4: I2C_FUNC_SMBUS_READ_WORD_DATA
7. SMBus Write Byte
I2C-tools中的函数:i2c_smbus_write_byte_data()。 先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的数据。
Functionality flag4: I2C_FUNC_SMBUS_WRITE_BYTE_DATA
8. SMBus Write Word
I2C-tools中的函数:i2c_smbus_write_word_data()。 先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的数据。
Functionality flag4: I2C_FUNC_SMBUS_WRITE_WORD_DATA
9. SMBus Block Read
I2C-tools中的函数:i2c_smbus_read_block_data()。
先发出Command Code(它一般表示芯片内部的寄存器地址),再发起度操作:
- 先读到一个字节(Block Count),表示后续要读的字节数
- 然后读取全部数据
Functionality flag4: I2C_FUNC_SMBUS_READ_BLOCK_DATA
10. SMBus Block Write
I2C-tools中的函数:i2c_smbus_write_block_data()。 先发出Command Code(它一般表示芯片内部的寄存器地址),再发出1个字节的Byte Conut(表示后续要发出的数据字节数),最后发全部数据。
Functionality flag4: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
11. I2C Block Read
在一般的I2C协议中,也可以连续读出多个字节。 它跟SMBus Block Read的差别在于设备发出的第1个数据不是长度N,如下图
示:
I2C-tools中的函数:i2c_smbus_read_i2c_block_data()。
先发出Command Code(它一般表示芯片内部的寄存器地址),再接收所有数据。
Functionality flag4: I2C_FUNC_SMBUS_READ_I2C_BLOCK
12. I2C Block Write
在一般的I2C协议中,也可以连续发出多个字节。 它跟SMBus Block Write的差别在于发出的第1个数据不是长度N,如下图所示:
I2C-tools中的函数:i2c_smbus_write_i2c_block_data()。
先发出Command Code(它一般表示芯片内部的寄存器地址),再发全部数据。
Functionality flag4: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
13. SMBus Block Write - Block Read Process Call
先写一块数据,再读一块数据。
Functionality flag4: I2C_FUNC_SMBUS_BLOCK_PROC_CALL
14. Packet Error Checking (PEC)
PEC是一种错误校验码,如果使用PEC,那么在P信号之前,数据发送方要发送一个字节的PEC码(它是CRC-8码)。
以SMBus Send Byte为例,下图中,一个未使用PEC,另一个使用PEC: