运行Micropython的STM32L476与MATLAB串口通信问题求助
问题根因分析
当前实现存在3类核心错误,是导致通信异常的直接原因:
- 串口资源操作错误:Micropython端
serial.Serial初始化默认会打开串口,循环内反复调用ser.open()、ser.close()会导致串口频繁启停,必然出现丢包、数据错乱问题 - 通信格式无统一约定:两端没有明确发送/接收的数据类型(字符串/二进制)、长度、分隔规则,MATLAB的
fprintf默认按ASCII字符串发送,Micropython的ser.read()默认仅读1个字节且返回bytes类型,直接和整数比较本身逻辑错误 - 读取逻辑不匹配:MATLAB无参数调用
fread(s)会读取串口缓冲区所有残留数据,加上Micropython端print()输出自带换行符,多次运行的残留数据累积,自然会返回长度不符的数组
修正方案
首先统一通信约定,避免粘包、解析错误:
所有数值先转为ASCII字符串发送,单个数之间用英文逗号
,分隔,一帧数据末尾加换行符\n作为结束标记,接收端读到换行符即认为一帧结束
1. 简化测试场景的STM32 Micropython代码
注意:STM32本地串口编号不是PC端识别的COM3,如果用Nucleo板载ST-Link虚拟串口,默认挂载USART2,直接用pyb.UART初始化即可;如果是外接USB转串口,按实际硬件端口调整即可。
from pyb import UART # 状态初始化 state = 'WAIT' # 串口仅初始化一次,不要反复开关 ser = UART(2, 115200, timeout=1) recv_buf = b'' # 接收缓冲区 while True: # 读取所有可用字节到缓冲区 if ser.any(): recv_buf += ser.read(ser.any()) # 检查是否收到完整帧(结束符\n) if b'\n' in recv_buf: # 切出完整帧,剩余数据留在缓冲区等待下一次解析 frame, recv_buf = recv_buf.split(b'\n', 1) # 尝试解析数值 try: V = int(frame.decode().strip()) except: # 解析失败直接跳过当前错误帧 continue # 状态逻辑处理 if state == 'WAIT': resp = 'WAITING\n' if V > 10: state = 'TEN' elif state == 'TEN': resp = 'TEN\n' if V < 10: state = 'WAIT' else: resp = 'END OF PROGRAM\n' # 发送响应,带结束符 ser.write(resp.encode())
2. 简化测试场景的MATLAB代码
%% 清理环境,释放残留串口占用 clear all clc delete(instrfindall); %% 串口配置 sobj = 'COM3'; s = serial(sobj,'BaudRate',115200,'timeout',2); fopen(s); %% 发送测试数据,按约定加结束符\n DatatoSend = 15; fprintf(s, '%d\n', DatatoSend); %% 读取完整响应,fgetl会读到换行符自动停止,自动丢弃换行符 data = fgetl(s); disp('STM32返回结果:'); disp(data); %% 关闭释放串口 fclose(s); delete(s); clear s
原业务场景适配说明
你原本需要传输3个1位小数、返回2个整数,按上述约定调整即可:
- MATLAB发送端:按格式拼接数据
fprintf(s, '%.1f,%.1f,%.1f\n', y(1), y(2), y(3)); - STM32接收端:把解析到的帧按逗号切分,分别转float即可得到3个传感器值
- STM32返回端:计算完成后按格式发送
ser.write(f'{ret1},{ret2}\n'.encode()),其中ret1、ret2为要返回的整数 - MATLAB接收端:拆分返回值得到目标数组
res = str2double(split(fgetl(s), ','));,返回的res就是2×1的整数数组
内容的提问来源于stack exchange,提问作者Ashloz
相关产品推荐
相关产品推荐

