注意

这是最新开发分支配套的文档,可能包含已发布版本中尚未提供的功能。如果您要查看特定版本的文档,请使用左侧的下拉菜单并选择所需要的版本。

uart_periodic_tx 模块 API 手册#

概述#

uart_periodic_tx 是一个可选的原生模块,用硬件定时器周期性发送已经准备好的完整 UART 帧。定时器回调只执行原生 UART 写操作,不执行 Python 代码,也不在回调中分配 GC 内存。

适用于需要稳定周期发送固定长度或有限长度数据帧的场景,例如每 50 ms 发送一次状态帧。应用程序在普通 Python 上下文中调用 update() 准备下一帧;模块会复制数据并在后续定时器触发时发送。

备注

该模块是 UART 周期发送器,不是通用硬件定时任务框架,不能在定时器中调度任意 Python 函数,也不能直接用于网络、SPI 或 I2C 传输。

启用模块#

该功能默认关闭。编译固件前,在源码根目录执行构建环境对应的配置命令:

# 使用 k230-builder 时
k230 make menuconfig

# 直接本机编译时
make menuconfig

打开以下选项后重新编译固件:

CanMV Micropython Components Configurations
    Enable UART periodic TX module

未启用该选项的固件中导入模块会报 ImportError

导入模块#

from machine import FPIOA, UART
from uart_periodic_tx import UARTPeriodicTx

快速开始#

以下示例将 UART3 的 TX 映射到 IO50,并每 50 ms 发送一帧。应根据开发板和板级配置选择未被 REPL 或其他系统功能占用的 UART 与引脚。

from machine import FPIOA, UART
from uart_periodic_tx import UARTPeriodicTx
import time

fpioa = FPIOA()
fpioa.set_function(50, FPIOA.UART3_TXD)

tx = UARTPeriodicTx(
    UART.UART3,
    0,
    50,
    max_len=64,
    baudrate=115200,
    bits=UART.EIGHTBITS,
    parity=UART.PARITY_NONE,
    stop=UART.STOPBITS_ONE,
    repeat_last=True,
)

try:
    tx.update(b"\xA5\x5A\x00\xFF\x3C\xC3\xFF\x0D")
    tx.start()

    time.sleep_ms(1000)
    tx.update(b"\xA5\x5A\x01\xFE\x3C\xC3\xFF\x0D")
    time.sleep_ms(1000)
finally:
    tx.deinit()

必须在调用 start() 前完成 FPIOA 的 UART TX 引脚映射。update() 会复制传入的缓冲区,因此调用返回后修改原始 bytearray 不会修改已经发布的帧。

UARTPeriodicTx#

构造函数#

UARTPeriodicTx(
    uart_id,
    timer_id,
    period=50,
    *,
    max_len=64,
    baudrate=115200,
    bits=UART.EIGHTBITS,
    parity=UART.PARITY_NONE,
    stop=UART.STOPBITS_ONE,
    repeat_last=True,
)

创建周期发送器。构造函数会分配三组发送缓冲区,但在调用 start() 前不会占用 UART 或硬件定时器。

参数

说明

uart_id

UART 硬件编号,例如 UART.UART3。传入的是编号而不是 machine.UART 对象。UART 必须可用且 TX 引脚已正确复用。

timer_id

硬件定时器编号。不能使用软件定时器编号 -1。当前 K230 定时器编号为 05

period

发送周期,单位为 ms,默认 50,最小值为 1

max_len

单帧最大长度,默认 64,范围为 14096 字节。模块为该容量分配三组缓冲区。

baudrate

UART 波特率,默认 115200

bits

数据位,使用与 machine.UART 相同的常量,例如 UART.EIGHTBITS。支持 5 到 9 位。

parity

校验方式,例如 UART.PARITY_NONEUART.PARITY_ODDUART.PARITY_EVEN

stop

停止位,例如 UART.STOPBITS_ONEUART.STOPBITS_TWO

repeat_last

是否在没有新的 update() 时重复发送最后一帧,默认 True。设为 False 时,每个成功 update() 的非空帧只在完整写入 UART 后发送一次;后续定时器触发会跳过,直到有新的 update()

period 可以作为第三个位置参数传入,其余 UART 配置参数必须使用关键字参数。

update 方法#

tx.update(data)

复制并发布一帧完整数据,供硬件定时器在后续触发时发送。

参数

  • data:支持缓冲区协议的数据,例如 bytesbytearraymemoryview。长度不能超过 max_len

异常

  • ValueError:对象已释放,或数据长度超过 max_len

  • OSError(EBUSY):三组缓冲区暂时都不可写。可在普通 Python 上下文中稍后重试;不要在 machine.Timer 回调中调用该方法。

update() 不会等待当前帧发送完成,也不保证新帧恰好在下一次硬件触发时出现。如果定时器回调已经取走当前缓冲区,新帧会在其后的触发中生效。repeat_last=True 时,定时器持续发送最近一次成功发布的完整帧;repeat_last=False 时,该帧完整写入一次后等待下一次 update()

start 方法#

tx.start()

申请硬件定时器和 UART,并开始周期发送。调用前至少应成功调用一次 update(),否则定时器触发会记为跳过发送。

同一个 timer_id 不能同时被 machine.Timer 或另一个 UARTPeriodicTx 使用。资源冲突会抛出 OSError(EBUSY)

stop 方法#

tx.stop()

停止周期发送并释放硬件定时器和 UART 的运行时资源,但保留对象和已分配的发送缓冲区。之后可以再次调用 start()

deinit 方法#

tx.deinit()

停止发送并释放全部原生资源和缓冲区。调用后对象不能再次使用。建议在 try / finally 中调用,确保异常路径也能释放硬件定时器。

active 方法#

tx.active()

返回布尔值,表示硬件定时器是否正在运行。

stats 方法#

sent, short_write, errors, skipped = tx.stats()

返回累计统计元组:

返回值

说明

sent

UART 写入返回完整帧长度的次数。

short_write

UART 写入了部分帧的次数。

errors

UART 写入返回错误的次数。

skipped

未发送的定时器触发次数,例如 UART 正在被另一个周期发送器写入、尚未发布可发送帧,或 repeat_last=False 时没有新数据。

统计值在对象生命周期内累计,stop() 和再次 start() 不会清零。

资源与时序约束#

  • UARTPeriodicTx 持有用于发送的原生 UART 驱动。运行期间不要通过 machine.UART.write() 发送同一 UART,也不要重新配置或释放同一 UART。

  • 多个 UARTPeriodicTx 可以使用同一 UART,但 UART 配置必须完全相同。两个发送时刻重叠时,其中一个触发会被跳过并计入 skipped。需要可预测时序时,应为一个 UART 只创建一个周期发送器。

  • 定时器触发由硬件定时器驱动,避免了 Python VM、GC 和 Python 回调带来的发送触发延迟;实际在线路上完成一帧仍受波特率、帧长度和 UART 驱动状态影响。

  • 帧的串行发送时间应明显小于 period。若帧过长、波特率过低或 UART 忙,可能出现 short_writeerrorsskipped

  • repeat_last=True 时,逻辑分析仪会看到最近成功 update() 的帧被连续发送。repeat_last=False 时,每次成功 update() 最多产生一次完整帧发送;没有新数据的触发会计入 skipped

完整回环验证示例见 UARTPeriodicTx 硬件定时发送

评论列表
条评论
登录