MicroPython 开发ESP32应用教程 之 UART 详细讲解及应用
一、UART基础概念
- UART(通用异步收发器)是一种双工串行通信协议,物理层由RX(接收)和TX(发送)两条线组成
- 通信单位是字符(8位或9位宽),采用起始位+数据位+停止位的帧格式传输
- 与并行通信相比,串行通信占用IO少但传输速率较低
二、UART类实现
1. 构造函数
from machine import UART uart = UART(id, baudrate=115200, bits=8, parity=None, stop=1, tx=17, rx=16, timeout=10)
参数说明:
id
:串口编号,ESP32支持0-2,ESP32的UART0默认用于REPL调试,项目开发建议使用UART2bits
:数据位长度(7/8/9),默认8位parity
:校验方式(None/0偶校验/1奇校验),启用时bits需设为7或8位stop
:停止位长度(1/2),默认1位rx/tx
:可指定接收/发送引脚号(如16, 17)
2. 核心方法
read(n)
/readinto(buf)
:读取指定字节数write(buf)
:发送数据readchar()
/writechar()
:单字符读写any()
:检测接收缓冲区数据量
三、timeout参数详解
一)、timeout参数的核心作用
在MicroPython的UART库中,timeout
参数用于设置读取操作的超时时间,其核心作用是:
- 控制接收操作的等待时间,避免无限阻塞
- 当指定时间内未接收到数据时返回空结果
- 单位是毫秒(ms),默认值为10ms
二)、具体工作机制
阻塞行为:
当调用read()
/readchar()
等方法时,UART会等待直到:
1) 或达到设置的timeout时间
2)接收到指定数量的数据超时处理:
1)超时发生后,方法返回已接收到的部分数据(如果有)
2)若未接收到任何数据则返回空对象
三)、实际应用场景
串口通信调试:
from machine import UART uart = UART(id, baudrate=115200, bits=8, parity=None, stop=1, tx=17, rx=16, timeout=100)data = uart.read(10) # 最多等待100ms
实时系统控制:
1)设置较短的timeout(如50ms)实现快速响应
2)设置较长的timeout(如500ms)确保完整接收
四)、参数设置建议
计算公式:
建议timeout = 数据帧传输时间 + 缓冲余量
数据帧时间 = (数据位+起始位+停止位)×(1/波特率)
典型值推荐:
- 低速通信(9600bps):100-200ms
- 高速通信(115200bps):20-50ms12
特殊处理:
- 对于大块数据传输,应设置更长timeout
- 实时性要求高的系统可使用轮询替代timeout
虽然看起来timeout参数作用很大,可以帮我们解决很多问题,但很多时候我们还是应该尽可能避免无谓的等待,让用户体验更好,这时中断机制就能解决我们面临的很多问题。
四、MicroPython UART中断机制详解
一)、UART中断基本概念
UART中断允许在数据到达时自动触发处理程序,避免轮询方式带来的CPU资源浪费。MicroPython通过回调函数机制实现中断处理,当特定事件发生时自动调用预设函数。
二)、中断配置方法
from machine import UARTdef uart_callback(t):while uart.any():print(uart.read())uart = UART(1, baudrate=115200, bits=8, parity=None, stop=1, tx=17, rx=16)
uart.irq(trigger=UART.RX_ANY, handler=uart_callback)
该代码展示了最基本的UART中断配置,当接收到任何数据时触发回调函数。
import micropython
from machine import UARTmicropython.alloc_emergency_exception_buf(100)
buffer = bytearray(256)def idle_handler(t):if uart.any():length = uart.readinto(buffer)process_data(buffer[:length])uart = UART(1, baudrate=115200, bits=8, parity=None, stop=1, tx=17, rx=16)
uart.irq(trigger=UART.RXIDLE, handler=idle_handler) # 线路空闲时触发
优势:适合高速通信,减少中断次数。如果处理接收到的数据需要占时较长的话,建议不要在中断回调函数中处理。不管什么中断回调函数,除非必要,尽可能简洁。
from machine import UARTdef uart1_handler(t):data = uart1.read(uart1.any())# 处理UART1数据def uart2_handler(t):data = uart2.read(uart2.any())# 处理UART2数据uart1 = UART(1, baudrate=115200, bits=8, parity=None, stop=1, tx=17, rx=16)
uart2 = UART(2, baudrate=115200, bits=8, parity=None, stop=1, tx=9, rx=10)
uart1.irq(handler=uart1_handler)
uart2.irq(handler=uart2_handler)
同时管理多个串口设备的代码。
三)、关键参数说明
- 触发条件:
- RX_ANY:接收到任意数据时触发
- RXIDLE:接收线路空闲时触发
- 回调函数设计原则:
- 必须包含伪参数(通常为t)
- 应尽量简短快速执行
- 避免内存分配和复杂操作
最近有个项目用于改造老产品,为老产品增加IOT功能,但客户产品的量不大,重新开发不管从哪方面评估都不划算,所以我们打算采用ESP32核心开发板来改造该产品,从而大大提高开发效率。这就是写这篇博文的原因,接下来我们会写一篇有关MQTT的博文。