Microbit串口uart.read()丢字节问题求助
Micro:bit串口接收大字节数据丢包问题排查与解决
问题现象
向Micro:bit发送8字节数据时可完整接收,但发送12字节及以上数据时接收状态不稳定:16字节数据有时能成功接收,22字节数据则从未成功。怀疑串口会拆分接收的数据,但拼接各数据段后仍存在丢字节情况。
原始代码
from microbit import * count = 0 def show_count_on_leds(c, brightness): display.clear() for i in range(min(c, 25)): x = i % 5 y = i // 5 display.set_pixel(x, y, brightness) buffer = b"" while True: sleep(10) if uart.any(): incoming = uart.read() if incoming: buffer += incoming count += len(incoming) if buffer and buffer[0] == ord('A') and buffer[-1] == ord('Z'): show_count_on_leds(count, 9) count = 0 buffer = b""
问题原因
- 串口缓冲区溢出:Micro:bit默认UART缓冲区容量有限,发送大字节数据时,循环中
sleep(10)的延迟加上LED显示操作的耗时,会导致程序无法及时读取串口数据,缓冲区满后新数据直接被丢弃。 - 帧同步逻辑不完善:当前代码仅检查缓冲区首尾是否为'A'和'Z',如果之前的残留数据未清空,或者数据拆分后某次接收的结尾不是'Z',会导致缓冲区积累无效数据,后续正确数据也无法触发处理逻辑。
- 固定延迟导致数据堆积:
sleep(10)让程序每10ms才检查一次串口,大流量数据发送时,这段时间内串口缓冲区可能已经塞满,造成丢包。
解决办法
1. 增大串口缓冲区
初始化UART时指定更大的缓冲区,减少溢出概率:
uart.init(baudrate=9600, bits=8, parity=None, stop=1, tx=pin0, rx=pin1, buffersize=128)
2. 优化帧同步与错误处理
- 自动丢弃缓冲区开头的无效数据,直到找到帧起始符'A';
- 增加超时机制,长时间未收到完整帧时重置缓冲区,避免无效数据堆积。
3. 减少循环延迟
去掉或缩短固定sleep,让程序更频繁地检查串口数据,避免数据堆积。
4. 优化LED显示操作
减少显示函数的耗时,避免占用过多处理时间影响串口读取。
5. 增加接收确认机制
Micro:bit收到完整帧后向发送端返回确认信号,发送端确认后再发送下一包,避免连续发送导致数据溢出。
修改后的示例代码
from microbit import * # 初始化UART,增大缓冲区至128字节 uart.init(baudrate=9600, bits=8, parity=None, stop=1, tx=pin0, rx=pin1, buffersize=128) count = 0 buffer = b"" last_receive_time = running_time() def show_count_on_leds(c, brightness): display.clear() max_pixels = min(c, 25) for i in range(max_pixels): x = i % 5 y = i // 5 display.set_pixel(x, y, brightness) while True: if uart.any(): incoming = uart.read() if incoming: buffer += incoming count += len(incoming) last_receive_time = running_time() # 丢弃开头的无效数据,直到找到起始符'A' while len(buffer) > 0 and buffer[0] != ord('A'): buffer = buffer[1:] count -= 1 # 检查是否收到完整帧(结尾为'Z') if buffer and buffer[-1] == ord('Z'): show_count_on_leds(count, 9) # 发送接收确认信号 uart.write(b'OK') count = 0 buffer = b"" # 超时处理:1秒未收到新数据则重置缓冲区 if running_time() - last_receive_time > 1000 and len(buffer) > 0: count = 0 buffer = b""
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

