树莓派I2C接口技术及Python SMBus、串行I2C EEPROM应用编程

目录

一、I2C接口技术

1. I2C总线系统组成

2. I2C总线的状态及信号

3. I2C总线基本操作

4. 启动和停止条件

5. I2C总线数据传输格式

二、I2C总线上拉电阻的估算与选取

三、树莓派与AT24C02接口实验电路及Python SMBus串行I2C EEPROM应用编程

1. 启动RPi串行I2C接口及安装Python SMBus库

2. 树莓派与AT24C02 EEPROM接口实验电路

3. Python SMBus库函数介绍

4. 使用I2C Tools及Python SMBus读写AT24C02 EEPROM


一、I2C接口技术

I2C接口是嵌入式系统中常用的网络接口之一,它采用串行通信方式将MCU/传感器连接到系统总线,通过主机/从机的方式协调工作。

I2C/IIC(Inter-Integrated Circuit)总线是由PHILIPS公司于1982年针对MCU/传感器等应用需求而研制的一种两线式串行总线,用于连接MCU及传感器等设备。

I2C总线的主要特点如下:

(1)I2C总线最主要的优点是其简单性和有效性。

(2)由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。

(3)I2C总线的长度可高达25英尺(约7.6m),并且能够以标准模式100Kbps的传输速率支持40个组件。新一代I2C总线还支持高速模式400Kbps传输。

(4)I2C总线的另一个优点是支持多主控(multi-mastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号传输和时钟频率。当然,在任何时间点上只能有一个主控。

1. I2C总线系统组成

I2C总线协议包含两层协议:物理层和数据链路层。

在物理层,I2C总线仅使用了两条信号线:一个是串行数据线SDA (Serial DAta line),它用于数据的发送和接收;另一个是串行时钟线SCL (Serial Clock Line)构成的串行总线,它用于指示何时数据线上是有效数据,即数据同步。MCU与被控IC之间、IC与IC之间进行双向传送,I2C标准模式最大传送速率为100kbps,I2C快速模式最大传输速率为400kbps。

在数据链路层,每个连接到I2C总线上的设备都有唯一的地址,设备的地址由系统设计者决定。在信息的传输过程中,I2C总线上并接的每一设备既是主设备(或从设备)又是发送器(或接收器),这取决于它所要完成的功能。

由I2C总线所构成的系统可以有多个I2C节点设备,并且可以是多主系统,任何一个设备都可以为主I2C;但是任一时刻只能有一个主I2C设备,I2C具有总线仲裁功能,以保证系统正确运行。主I2C设备发出时钟信号、地址信号和控制信号,选择通信的从I2C设备并控制收发。

I2C总线要求:(1)各个节点设备必须具有I2C接口功能;(2)各个节点设备必须共地;(3)两根信号线必须接上拉电阻Rp。如图1所示。

图1 多I2C设备接口示意图



 

2. I2C总线的状态及信号

(1)空闲状态

SCL和SDA均处于高电平状态,即为总线空闲状态(空闲状态为何是高电平的道理很简单,因为它们都接上拉电阻)。

(2)占有总线和释放总线

若想让器件使用总线应当先占有它,占有总线的主控器向SCL线发出时钟信号。数据传送完成后应当及时释放总线,即解除对总线的控制(或占有),使其恢复成空闲状态。

(3)启动信号[S]

启动信号由主控器产生。在SCL信号为高时,SDA产生一个由高变低的电平变化,产生启动信号。

(4)结束/停止信号[P]

当SCL线高电平时,主控器在SDA线上产生一个由低电平向高电平跳变,产生停止信号。启动信号和停止信号的产生见图2所示。

在这里插入图片描述 图2 启动信号和停止信号的产生

 

(5)应答/响应信号[A/NA]

应答信号是对字节数据传输的确认。应答信号占1位,数据接收者接收1字节数据后,应向数据发出者发送一个应答信号。对应于SCL第9个应答时钟脉冲,若SDA线仍保持高电平,则为非应答信号(NA/ACK)。低电平为应答,继续发送;高电平为非应答,结束发送。

(6)控制位信号[R/nW]

控制位信号占1位,IIC主机发出的读写控制信号,高为读、低为写(对IIC主机而言)。控制位(或方向位)在寻址字节中给出。

(7)地址信号

地址信号为从机地址,占7位,称之为“寻址字节”(见表1)。
 

在这里插入图片描述 表1 寻址字节

 

下面对表1中的各字段进行说明。

器件地址(DA3-DA0):DA3-DA0是I2C总线接口器件固有的地址编码,由器件生产厂家给定,如AT24C××I2C总线EEPROM器件的地址为1010等。

引脚地址(A2、A1、A0):引脚地址由I2C总线接口器件的地址引脚A2、A1、A0的高低来确定,接高电平者为1,接地者为0。

读写控制位/方向位(R/n W):R/nW为1表示主机读,R/nW为0表示主机写。

7位地址和读写控制位组成1个字节,即寻址字节。

(8)等待状态

在IIC总线中,赋予接收数据的器件具有使系统进行等待状态的权力,但等待状态只能在一个数据字节完整接收之后进行。例如,当进行主机发送从机接收的数据传送操作时,若从机在接收到一个数据字节后,由于中断处理等原因而不能按时接收下一个字节;从机可以通过把SCL下拉为低电平,强行使主机进入等待状态;在等待状态下,主机不能发送数据,直到从机认为自己能继续接收数据时,再释放SCL线,使系统退出等待状态,主机才可以继续进行后续的数据传送。
 

3. I2C总线基本操作

(1)串行数据线SDA和串行时钟线SCL在连接到总线的器件间传递信息。

(2)每个器件都有一个唯一的地址标识,无论是MCU、LCD驱动器、存储器或键盘接口。

(3)每个器件都可以作为一个发送器或接收器,由器件的功能决定。显然,LCD驱动器只是一个接收器,而存储器则既可以接收又可以发送数据。

(4)除了将器件看作发送器和接收器外,在执行数据传输时它也可以被看作是主机或从机。

(5)主机是初始化总线的数据传输并产生允许传输时钟信号的器件,此时任何被寻址的器件都被看作是从机。
 

4. 启动和停止条件

在SCL 线是高电平时,SDA 线从高电平向低电平切换,这个情况称为启动条件。当SCL是高电平时,SDA 线由低电平向高电平切换,称为停止条件。

启动和停止条件一般由主机产生。总线在启动条件后被认为处于忙的状态,在停止条件的某段时间后,总线被认为再次处于空闲状态。如果产生重复启动条件Sr而不产生停止条件P,总线将一直处于忙状态。
 

5. I2C总线数据传输格式

I2C总线数据传输格式见图3所示。在图3中,S为启动信号,R/nW为读写控制位,A/NA为应答信号,P为停止信号。

在这里插入图片描述 图3 I2C总线数据传输格式



 

二、I2C总线上拉电阻的估算与选取

由于I2C设备的SCL、SDA总线是漏极开路的,因此在前面的图1中, I2C总线的SCL、SDA引脚必须外接上拉电阻Rp。

一般I2C的上拉电阻Rp在1 kΩ∽10 kΩ之间选取,如,Rp可以取1.5kΩ、1.8kΩ、2.2kΩ、4.7kΩ、5.1kΩ、6.8kΩ、10kΩ等典型值,上拉电阻的大小对时序有一定影响,对信号的上升时间和下降时间也有影响。

I2C上拉电阻Rp选取估算公式如下:

Rpmin={VDD(min)-0.4V}/3mA
Rpmax=(T/0.874) *C (T=1us, 100KHz; T=0.3us, 400KHz)

C是总线电容(Bus Capacitance)或总线负载电容。

Rp最大值由总线电容最大值CBmax决定,Rp最小值由VIO(VDD)与上拉驱动电流(设最大值为3mA)决定;

关于Rpmin的取值:在5V供电的嵌入式系统中,有Rpmin=5V/3mA≈1.7kΩ;在3.3V供电的嵌入式系统中,有Rpmin=3.3V/3mA=1.1kΩ;在2.8V供电的嵌入式系统中,有Rpmin=2.8V/3mA≈1kΩ。

关于Rpmax的取值:在I2C标准模式下,100Kbps总线负载电容最大值<=400pF;在I2C快速模式下,400Kbps总线的负载电容最大值<=200pF。根据具体的使用场景、当前的器件制造工艺、PCB的走线距离等因素以及标准向下兼容性,设计中以I2C快速模式为基础,即总线负载电容<200pF时,传输速度达到400Kbps是不成问题的,现按5V供电系统对应于50pF∽200pF估算,有Rpmax取值范围是1.7kΩ∽6.9kΩ。根据Rpmin与Rpmax的限制范围,在5V供电的嵌入式系统中,可取Rp=5.1kΩ, 总线负载电容的环境要求也容易达到;在3.3V供电的嵌入式系统中,可选Rp=1.8kΩ∽4.7kΩ;在2.8V供电的嵌入式系统中,控制台应用可选Rp=1.5kΩ∽2.2kΩ,可穿戴式或便携式等低供耗应用可选Rp=4.7kΩ牺牲速度来换取电池使用时间。总之,电源电压限制了上拉电阻Rp的最小值;总线负载电容(总线电容)限制了上拉电阻Rp的最大值。
 

三、树莓派与AT24C02接口实验电路及Python SMBus串行I2C EEPROM应用编程

如果使用树莓派I2C总线控制外设或传感器,则树莓派一般工作于主机模式。树莓派I2C总线遵守SMBus(System Management Bus,系统管理总线)协议。从类型上说,SMBus协议可看成是I2C总线协议的子类,采用Python语言访问I2C设备可直接使用SMBUS库/SMBUS模块。
 

1. 启动RPi串行I2C接口及安装Python SMBus库

默认情况下,I2C总线是禁止使用的,我们可以在Linux终端用raspi-config工具启动IC2接口,运行raspi-config工具命令如下:

$ sudo raspi-config

运行后按菜单提示,即可启动I2C接口。

另一种启动I2C接口的方法是在Preferences的主菜单中找到Raspberry Pi Configuration工具启动I2C接口。

安装Python的I2C库SMBus的方法是输入以下命令:

$ sudo apt-get install python-smbus

为了使这些修改有效,需要重新引导树莓派。
 

2. 树莓派与AT24C02 EEPROM接口实验电路

以树莓派3B为例,RPi 3B与AT24C02 EEPROM接口实验电路原理图见图4所示。由图4可知,RPi 3B串行I2C总线自带1.8kΩ上拉电阻,因此,RPi 3B串行I2C总线与AT24C02接口无需再外接上拉电阻。需要强调的是,是否在I2C总线外接上拉电阻,要看所使用的开发板是否自带I2C总线上拉电阻;若开发板没有提供I2C总线上拉电阻,则需按前面的I2C总线上拉电阻估算方法外接两个上拉电阻Rp。

在这里插入图片描述 图4 RPi 3B与AT24C02 EEPROM接口实验电路原理图

 

为方便起见,这里使用面包板搭建RPI 3B与AT24C02接口实验电路,ATC24C02的VCC与RPi 3B的3.3V电源Pin1物理引脚连接,GND与RPI 3B的GND接地引脚Pin14连接,SCL与RPI 3B的I2C-1串行时钟线SCL.1的Pin14物理引脚连接,SCL与RPI 3B的I2C-1串行数据线SDA.1的Pin3物理引脚连接。这里,地址线A0、A1、A2都接地,查看AT24C02器件手册可知,在此配置下,I2C设备AT24C02地址是0x50 (注意:树莓派中的I2C设备地址计算是根据I2C器件的实际寻址地址0b1010A2A1A0得出的,故AT24C02设备寻址地址为0b1010000=0x50;如果按I2C器件手册中给出的带读写控制位的寻址地址字节为0b1010A2A1A0R/nW,即写I2C器件寻址地址为0xa0, 读I2C器件寻址地址为0xa1), 写保护WP接地,这样树莓派就能正常读写I2C设备了。实验接口电路连接好后,建议先用万用表检查接口连线是否正确(特别注意电源和地之间不能短路),然后再开机启动树莓派对AT24C02器件进行读写操作(见图5)。

在这里插入图片描述 图5 RPI 3B与AT24C02接口实验电路接线图


 

3. Python SMBus库函数介绍

在树莓派中,我们可用Python SMBus库函数访问串行I2C设备,导入SMBus模块及常用SMBus库函数介绍如下。

(1) Import SMBus
●To access I2C bus on Raspberry Pi using SMBus Python module, import SMBus module as follows.
import smbus
●Create object of SMBus class to access I2C based Python function.
= smbus.SMBus(I2C port no.)
I2C port no : I2C port no. i.e. 0 or 1
●Example - Bus = smbus.SMBus(1)
Now, we can access SMBus class with Bus object.

(2) Bus.write_byte_data(Device Address, Register Address, Value)
●This function is used to write data to the required register.
Device Address : 7-bit or 10-bit device address
Register Address : Register address to which we need to write
Value : pass value which needs to write into the register
●Example - Bus.write_byte_data(0x68, 0x01, 0x07)

(3) Bus.write_i2c_block_data(Device Address, Register Address, [value1, value2,….])
●This function is used to write a block of 32 bytes.
Device Address : 7-bit or 10-bit device address
Register Address : Register address to which we need to write data
Value1 Value2…. : write a block of bytes to the required address
●Example - Bus.write_i2c_block_data(0x68, 0x00, [0, 1, 2, 3, 4, 5]) # write 6 bytes of data from 0 address.

(4) Bus.read_byte_data(Device Address, Register Address)
●This function is used to read data byte from required register.
Device Address : 7-bit or 10-bit device address
Register Address : Register address from which we need to read data
●Example - Bus.read_byte_data (0x68, 0x01)

(5) Bus.read_i2c_block_data(Device Address, Register Address, block of bytes)
●This function is used to read a block of 32 bytes.
Device Address – 7-bit or 10-bit device address
Register Address – Register address from which we need to read data
Block of Bytes – read no of bytes from the required address
●Example - Bus.read_i2c_block_data(0x68, 0x00, 8) # return value is a list of 6 bytes
 

4. 使用I2C Tools及Python SMBus读写AT24C02 EEPROM

在树莓派终端输入以下命令,安装I2C Tools:

pi@yuanzy:~ $ sudo apt-get install i2c-tools

接下来,针对图4的实验接口电路,用 I2C Tools 命令对AT24C02基本读写操作功能进行检验。在下面的I2C Tools各命令中, I2C使用树莓派的 I2C-1(SCL.1, SDA.1),AT24C02设备地址为0x50。

pi@yuanzy:~ $ sudo i2cdetect -l
i2c-1 i2c bcm2835 I2C adapter
pi@yuanzy:~ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: – -- – -- – -- – -- – -- – -- –
10: – -- – -- – -- – -- – -- – -- – -- – --
20: – -- – -- – -- – -- – -- – -- – -- – --
30: – -- – -- – -- – -- – -- – -- – -- – --
40: – -- – -- – -- – -- – -- – -- – -- – --
50: 50 51 – -- – -- – -- – -- – -- – -- – --
60: – -- – -- – -- – -- – -- – -- – -- – --
70: – -- – -- – -- – --
pi@yuanzy:~ $ sudo i2cdump -y 1 0x50
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
10: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
20: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
30: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
40: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
50: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff …

以上i2cdump显示了AT24C02设备所有字节单元的内容,因为是新购置芯片,故其256个字节单元为全1或0xff(即芯片内容为空)。

pi@yuanzy:~ $ sudo i2cset -y 1 0x50 0x00 0x60
pi@yuanzy:~ $ sudo i2cget -y 1 0x50 0x00
0x60

上面使用i2cset命令向AT24C02设备0#字节单元写入0x60,i2cget 读取AT24C02设备0#字节单元内容显示为0x60,说明写入的数据与读取的数据一致,树莓派读写AT24C02设备操作正常。

下面是用Python和Python SMBus库函数编写名为I2CAT24C02.py的程序向AT24C02器件256字节单元顺序写入0~255,然后再顺序读取AT24C02中的字节单元并显示输出,程序清单见图6所示。

在这里插入图片描述 图6 读写AT24C02 I2C EEPROM Python程序

 

I2CAT24C02.py程序顺序读取AT24C02中的256字节单元显示结果见图7所示。

在这里插入图片描述 图7 Python程序读取AT24C02设备256字节单元的内容并显示


 

还可使用I2C Tools的i2cdump命令显示AT24C02中的256字节单元内容(见图8)。由图7和图8可知,读取AT24C02设备字节单元内容的显示结果与写入到AT24C02设备字节单元的数据完全相同。
 

在这里插入图片描述 图8 i2cdump命令显示AT24C02设备256字节单元的内容

你可能感兴趣的:(树莓派I2C接口技术及Python SMBus、串行I2C EEPROM应用编程)