class UART -- 双工串行通信总线

UART 实现了标准的 UART/USART 双工串行通信协议。在物理层面上它由 2 条线组成:RX 和 TX。通信的基本单位是一个字符(不要与字符串中的字符混淆),其宽度可以是 8 位或 9 位。

可以使用以下方式创建并初始化 UART 对象::

from pyb import UART

# init with the given baudrate
uart = UART(3, 9600, timeout_char=1000)

# init with explicit parameters
uart.init(9600, bits=8, parity=None, stop=1, timeout_char=1000)

Bits 可以是 7、8 或 9。Parity 可以是 None、0(偶校验)或 1(奇校验)。Stop 可以是 1 或 2。

注意: 当 parity=None 时,仅支持 8 位和 9 位。启用校验时,仅支持 7 位和 8 位。

UART 对象的行为类似于 stream 对象,读取和写入通过标准的流方法完成::

uart.read(10)       # read 10 characters, returns a bytes object
uart.read()         # read all available characters
uart.readline()     # read a line
uart.readinto(buf)  # read and store into the given buffer
uart.write('abc')   # write the 3 characters

单个字符可以使用以下方式读取/写入::

uart.readchar()     # read 1 character and returns it as an integer
uart.writechar(42)  # write 1 character

要检查是否有可读取的数据,请使用::

uart.any()          # returns the number of characters waiting

注意: 流函数 readwrite 等是 MicroPython v1.3.4 中新增的。更早的版本使用 uart.senduart.recv

构造函数

class pyb.UART(bus: int | str, *args, **kwargs)

在给定的 bus(一个整数外设索引,例如 3 表示 UART3)上构造一个 UART 对象。若不提供其他参数,则只创建对象而不初始化(它会保留之前的总线设置,如果有的话);若提供了额外参数,则会初始化总线。可用参数请参阅 init()

UART(3) 在每个 STM32 OpenMV Cam 上都连接到相同的排针引脚:

信号

排针引脚

TX

P4

RX

P5

某些开发板上还提供额外的 UART 总线:

总线

TX 引脚

RX 引脚

可用于

UART(1)

P1

P0

OpenMV Cam M7 / H7 / H7 Plus / Pure Thermal

UART(4)

P2

P3

OpenMV Cam N6

UART(7)

P14

P13

OpenMV Cam N6

方法

init(baudrate: int, bits: int = 8, parity: int | None = None, stop: int = 1, *, timeout: int = 1000, flow: int = 0, timeout_char: int = 0, read_buf_len: int = 64) None

使用给定的参数初始化 UART 总线:

  • baudrate 是时钟速率。

  • bits 是每个字符的位数,可为 7、8 或 9。

  • parity 是校验方式,可为 None、0(偶校验)或 1(奇校验)。

  • stop 是停止位的数量,可为 1 或 2。

  • flow 设置流控制类型。可以是 0、UART.RTSUART.CTSUART.RTS | UART.CTS

  • timeout 是等待写入/读取第一个字符的超时时间,单位为毫秒。

  • timeout_char 是写入或读取时字符之间等待的超时时间,单位为毫秒。

  • read_buf_len 是读取缓冲区的字符长度(设为 0 可禁用)。

如果波特率无法设置到与期望值相差 5% 以内,此方法将引发异常。

注意: 当 parity=None 时,仅支持 8 位和 9 位。启用校验时,仅支持 7 位和 8 位。

deinit() None

关闭 UART 总线。

any() int

返回等待读取的字节数(可能为 0)。

read(nbytes: int | None = None) bytes | None

读取字符。如果指定了 nbytes,则最多读取这么多字节。如果缓冲区中有 nbytes 个字节可用,则立即返回,否则在足够的字符到达或超时结束时返回。

如果未提供 nbytes,则该方法会尽可能多地读取数据。它会在超时结束后返回。

注意: 对于 9 位字符,每个字符占用两个字节,nbytes 必须为偶数,字符数为 nbytes/2

返回值:一个包含所读入字节的 bytes 对象。超时时返回 None

readchar() int

在总线上接收单个字符。

返回值:以整数形式返回所读取的字符。超时时返回 -1。

readinto(buf: bytearray, nbytes: int | None = None) int | None

将字节读入 buf。如果指定了 nbytes,则最多读取这么多字节。否则,最多读取 len(buf) 个字节。

返回值:读取并存入 buf 的字节数,超时时返回 None

readline() bytes | None

读取一行,以换行符结尾。如果存在这样的一行,则立即返回。如果超时结束,则无论是否存在换行符都返回所有可用数据。

返回值:读取到的行,如果没有可用数据则在超时时返回 None

write(buf: bytes | bytearray | str) int | None

将字节缓冲区写入总线。如果字符宽度为 7 位或 8 位,则每个字节为一个字符。如果字符宽度为 9 位,则每个字符使用两个字节(小端序),并且 buf 必须包含偶数个字节。

返回值:写入的字节数。如果发生超时且未写入任何字节,则返回 None

writechar(char: int) None

在总线上写入单个字符。char 是要写入的整数。启用 CTS 流控制时的阻塞语义请参阅下面的 CTS 流控制 一节。

sendbreak() None

在总线上发送一个 break(间断)信号。这会将总线拉低,持续时长为 13 个位。

常量

RTS: int

用于 init()flow 参数的位标志;在接收路径上启用 RTS(请求发送)硬件流控制。

CTS: int

用于 init()flow 参数的位标志;在发送路径上启用 CTS(清除发送)硬件流控制。可以与 RTS 进行 OR 运算以同时启用两个方向。

流控制

UART(3) 支持 RTS/CTS 硬件流控制。在 OpenMV Cam M7、H7、H7 Plus 和 Pure Thermal 上,流控制引脚为:

(TX, RX, nRTS, nCTS) = (P4, P5, P1, P2)

在 OpenMV Cam N6 上仅暴露了 nRTS(位于排针引脚 P7);nCTS 没有连接到 I/O 排针。

在以下段落中,术语“目标设备”指的是连接到 UART 的设备。

当 UART 的 init() 方法在调用时将 flow 设置为 UART.RTSUART.CTS 之一或两者时,相应的流控制引脚会被配置。nRTS 是一个低电平有效的输出,nCTS 是一个启用了上拉的低电平有效输入。要连接流控制,请将 OpenMV Cam 的 nCTS 连接到目标设备的 nRTS,并将 OpenMV Cam 的 nRTS 连接到目标设备的 nCTS

CTS:目标设备控制 OpenMV Cam 的发送端

如果启用了 CTS 流控制,则写入行为如下:

如果调用了 OpenMV Cam 的 UART.write(buf) 方法,则在 nCTSFalse 的任何期间传输都会停顿。如果整个缓冲区未能在超时时间内传输完毕,这将导致超时。该方法返回写入的字节数,使用户能够在需要时写入剩余的数据。在发生超时的情况下,会有一个字符保留在 UART 中等待 nCTS。组成该字符的字节数将包含在返回值中。

如果在 nCTSFalse 时调用 UART.writechar(),则该方法会超时,除非目标设备及时置位 nCTS。如果超时,将引发 OSError 116。一旦目标设备置位 nCTS,该字符就会被发送。

RTS:OpenMV Cam 控制目标设备的发送端

如果启用了 RTS 流控制,则行为如下:

如果使用了带缓冲的输入(read_buf_len > 0),则会缓冲传入的字符。如果缓冲区变满,下一个到达的字符将导致 nRTS 变为 False:目标设备应当停止传输。当从缓冲区读取字符时,nRTS 将变为 True

请注意,any() 方法返回缓冲区中的字节数。假设缓冲区长度为 N 字节。如果缓冲区变满,又有一个字符到达,nRTS 将被置为 False,any() 将返回计数 N。当读取字符后,那个额外的字符将被放入缓冲区,并会包含在后续 any() 调用的结果中。

如果未使用带缓冲的输入(read_buf_len == 0),则一个字符的到达将导致 nRTS 变为 False,直到该字符被读取。