class I2C – 一种两线串行协议

I2C是一种用于设备间通信的两线协议。在物理层面上,它由两根线组成:SCL和SDA,分别为时钟线和数据线。

I2C 对象被创建并连接到特定的总线上。它们可以在创建时初始化,也可以稍后初始化。

打印I2C对象会给你显示其他配置信息。

硬件和软件I2C的实现都通过 machine.I2Cmachine.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 对象。

I2C.readfrom_mem_into(addr, memaddr, buf, *, addrsize=8)

从*addr*指定的外设从*memaddr*指定的内存地址开始读入*buf*。读取的字节数是*buf*的长度。参数* addressize *指定地址大小(以位为单位)。

方法返回 None

I2C.writeto_mem(addr, memaddr, buf, *, addrsize=8)

从*memaddr*指定的内存地址开始,将*buf*写入*addr*指定的外设。参数* addressize *指定地址大小(以位为单位)。

方法返回 None