class I2C – 一种两线串行协议¶
I2C是一种用于设备间通信的两线协议。在物理层面上,它由两根线组成:SCL和SDA,分别为时钟线和数据线。
I2C 对象被创建并连接到特定的总线上。它们可以在创建时初始化,也可以稍后初始化。
打印I2C对象会给你显示其他配置信息。
硬件和软件I2C的实现都通过 machine.I2C 和 machine.SoftI2C
类。硬件I2C使用系统的底层硬件支持来执行读/写操作,通常效率高且快速,但可能对可用的引脚有限制。软件I2C通过bit-banging实现,可以在任何引脚上使用,但效率不如硬件I2C。这些类有相同的方法可用,主要区别在于它们的构造方式。
备注
I2C总线需要在SDA和SCL上有上拉电路才能操作。通常这些是1 - 10 kOhm范围内的电阻,从每个SDA/SCL连接到Vcc。没有这些,行为是未定义的,可能从阻塞、意外的看门狗复位到错误的值都有。通常,这种上拉电路已经内置在MCU板或传感器断路板上,但这并非硬性规定。所以如果遇到问题,请检查。也可以参考Adafruit关于I2C接线的这篇优秀的 学习指南。
示例用法:
from machine import I2C
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
# depending on the port, extra parameters may be required
# to select the peripheral and/or pins to use
i2c.scan() # scan for peripherals, returning a list of 7-bit addresses
i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42
i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42,
# starting at memory-address 8 in the peripheral
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42
# starting at address 2 in the peripheral
构造函数¶
- class machine.I2C(id, *, scl, sda, freq=400000, timeout=50000)¶
使用以下参数构造并返回一个新的I2C对象:
id 标识特定的I2C外设。允许的值取决于特定的移植版本/板
scl 应该是一个引脚对象,指定用于SCL的引脚。
sda 应该是一个引脚对象,指定用于SDA的引脚。
freq 应该是一个整数,设置SCL的最大频率。
timeout 是允许I2C事务的最大时间(微秒)。某些移植版本上不允许此参数。
请注意,某些移植版本/板可能有*scl*和*sda*的默认值,可以在此构造函数中更改。其他的可能有固定的*scl*和*sda*值,无法更改。
- class machine.SoftI2C(scl, sda, *, freq=400000, timeout=50000)¶
构造一个新的软件I2C对象。参数为:
scl 应该是一个引脚对象,指定用于SCL的引脚。
sda 应该是一个引脚对象,指定用于SDA的引脚。
freq 应该是一个整数,设置SCL的最大频率。
timeout 是等待时钟拉伸的最大时间(微秒)(SCL由总线上的另一个设备保持低电平),之后会抛出
OSError(ETIMEDOUT)
异常。
通用方法¶
- I2C.init(scl, sda, *, freq=400000)¶
使用给定的参数初始化I2C总线:
scl 是SCL线的引脚对象
sda 是SDA线的引脚对象
freq 是SCL时钟频率
在硬件I2C的情况下,实际的时钟频率可能低于请求的频率。这取决于平台硬件。实际频率可以通过打印I2C对象来确定。
- I2C.deinit()¶
关闭 I2C 总线。
可用性:WiPy。
- I2C.scan()¶
扫描0x08到0x77之间的所有I2C地址,并返回响应的列表。如果设备在其地址(包括写入位)发送到总线后,将SDA线拉低,则认为该设备响应。
原始I2C操作¶
以下方法实现了原始I2C控制器总线操作,可以组合使用以进行任何I2C事务。如果你需要对总线有更多控制,可以提供这些方法,否则可以使用标准方法(见下文)。
这些方法仅在 machine.SoftI2C
类上可用。
- I2C.start()¶
在总线上生成一个START条件(SDA在SCL为高时过渡到低电平)。
- I2C.stop()¶
在总线上生成一个STOP条件(SDA在SCL为高时过渡到高电平)。
- I2C.readinto(buf, nack=True, /)¶
从总线读取字节并存储到 buf 中。读取的字节数是 buf 的长度。在接收最后一个字节之前的所有字节后,将在总线上发送一个ACK。在接收到最后一个字节后,如果 nack 为真,则发送一个NACK,否则发送一个ACK(在这种情况下,外设假设稍后会读取更多字节)。
- I2C.write(buf)¶
将 buf 中的字节写入总线。检查在 buf 的每个字节写入后是否收到ACK,并在收到NACK时停止传输剩余的字节。函数返回收到的ACK数量。
标准总线操作¶
以下方法实现了针对给定外设设备的标准I2C控制器读写操作。
- I2C.readfrom(addr, nbytes, stop=True, /)¶
从由*addr*指定的外设读取*nbytes*字节。如果*stop*为真,则在传输结束时生成一个STOP条件。返回一个包含读取数据的
bytes
对象。
- I2C.readfrom_into(addr, buf, stop=True, /)¶
从由 addr 指定的外设读取到 buf 中。读取的字节数将是 buf 的长度。如果 stop 为真,则在传输结束时生成一个STOP条件。
方法返回
None
。
- I2C.writeto(addr, buf, stop=True, /)¶
将 buf 中的字节写入由 addr 指定的外设。如果在从 buf 写入一个字节后收到一个NACK,则不会发送剩余的字节。如果 stop 为真,则即使收到NACK,也会在传输结束时生成一个STOP条件。函数返回收到的ACK数量。
- I2C.writevto(addr, vector, stop=True, /)¶
将 vector 中包含的字节写入由 addr 指定的外设。vector 应该是包含具有缓冲协议的对象的元组或列表。addr 发送一次,然后 vector 中每个对象的字节依次写出。vector 中的对象可以是长度为零的,在这种情况下它们不会对输出有贡献。
如果在从 vector 中的一个对象写入一个字节后收到一个NACK,则不会发送剩余的字节和任何剩余的对象。如果 stop 为真,则即使收到NACK,也会在传输结束时生成一个STOP条件。函数返回收到的ACK数量。
内存操作¶
某些I2C设备充当内存设备(或一组寄存器),可以从中读取和写入。在这种情况下,I2C事务有两个相关的地址:外设地址和内存地址。以下方法是与此类设备通信的便利函数。
- I2C.readfrom_mem(addr, memaddr, nbytes, *, addrsize=8)¶
从由 addr 指定的外设的 memaddr 指定的内存地址开始读取 nbytes 字节。addrsize 参数指定地址大小(位)。返回一个包含读取数据的
bytes
对象。