You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 05:06:06