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

Python解析嵌入式系统UART串口缓冲区字符串的最优方案

Python脚本解析UART传来的结构化命令

我刚好做过类似的UART命令解析项目,结合你给出的命令格式,给你整理了一套完整的可运行脚本,附带详细说明:

准备工作

首先得安装串口操作的Python库,打开终端跑这条命令:

pip install pyserial

核心思路

你的命令格式是S;SEND;40;{"ID":"asg01","T":1,"P":{"T":180}};E,结构很清晰:

  • 以S开头,E结尾,用分号;分隔字段
  • 字段依次是:起始标记、命令类型、载荷长度、JSON载荷、结束标记

我们的处理逻辑要做到:

  1. 从UART读取字节流,处理可能的粘包问题(比如一次读不全一条命令)
  2. 识别完整的命令(从S到E的完整片段)
  3. 拆分字段并做合法性校验(开头结尾、载荷长度匹配)
  4. 解析JSON载荷,执行对应操作

完整代码示例

import serial
import json
from time import sleep

def init_uart(port='COM3', baudrate=115200, timeout=1):
    """初始化UART串口"""
    try:
        ser = serial.Serial(port, baudrate, timeout=timeout)
        print(f"成功打开串口: {port}")
        return ser
    except Exception as e:
        print(f"串口打开失败: {str(e)}")
        return None

def parse_uart_command(raw_data):
    """解析单条UART命令"""
    # 先把字节转成字符串,去掉无关的空白字符
    command_str = raw_data.decode('utf-8').strip()
    
    # 校验开头和结尾
    if not (command_str.startswith('S;') and command_str.endswith(';E')):
        print(f"无效命令格式: {command_str}")
        return None
    
    # 拆分字段
    parts = command_str.split(';')
    # 正常拆分后应该是 ['S', 'SEND', '40', '{"ID":"asg01",...}', 'E'] 共5个元素
    if len(parts) != 5:
        print(f"命令字段数量错误: {command_str}")
        return None
    
    start_tag, cmd_type, payload_len_str, payload_str, end_tag = parts
    
    # 校验载荷长度
    try:
        payload_len = int(payload_len_str)
        if len(payload_str) != payload_len:
            print(f"载荷长度不匹配: 预期{payload_len},实际{len(payload_str)}")
            return None
    except ValueError:
        print(f"载荷长度格式错误: {payload_len_str}")
        return None
    
    # 解析JSON载荷
    try:
        payload = json.loads(payload_str)
    except json.JSONDecodeError as e:
        print(f"JSON解析失败: {str(e)}")
        return None
    
    return {
        'command': cmd_type,
        'payload': payload
    }

def execute_command(parsed_cmd):
    """根据解析后的命令执行对应操作"""
    if not parsed_cmd:
        return
    
    cmd_type = parsed_cmd['command']
    payload = parsed_cmd['payload']
    
    if cmd_type == 'SEND':
        # 这里写你要执行的操作,比如打印参数、调用其他函数
        print(f"收到SEND命令,设备ID: {payload['ID']},类型T: {payload['T']},参数P: {payload['P']}")
        # 示例:如果T=1,执行某个动作
        if payload['T'] == 1:
            print(f"执行温度相关操作,目标温度: {payload['P']['T']}℃")
    else:
        print(f"未处理的命令类型: {cmd_type}")

def main():
    # 初始化串口,注意端口号要改成你实际的(Windows是COMx,Linux是/dev/ttyUSBx)
    ser = init_uart(port='COM3')
    if not ser:
        return
    
    # 缓存串口数据,处理粘包
    buffer = b''
    
    try:
        while True:
            # 读取串口数据
            if ser.in_waiting > 0:
                buffer += ser.read(ser.in_waiting)
                # 检查是否有完整的命令(以;E结尾)
                while b';E' in buffer:
                    # 拆分出第一条完整命令
                    cmd_end_idx = buffer.index(b';E') + 2  # +2是包含;E的长度
                    raw_cmd = buffer[:cmd_end_idx]
                    buffer = buffer[cmd_end_idx:]  # 剩下的留在缓存里处理下一条
                    
                    # 解析并执行命令
                    parsed_cmd = parse_uart_command(raw_cmd)
                    execute_command(parsed_cmd)
            sleep(0.1)
    except KeyboardInterrupt:
        print("\n用户终止程序")
    except Exception as e:
        print(f"运行出错: {str(e)}")
    finally:
        if ser.is_open:
            ser.close()
            print("串口已关闭")

if __name__ == '__main__':
    main()

代码细节说明

  • 串口初始化:init_uart函数负责打开串口,你需要把port参数改成你实际的串口(比如Linux下的/dev/ttyUSB0,Windows下的COM3)
  • 粘包处理:用buffer缓存收到的字节流,每次找到;E结尾就拆分出完整命令,剩下的继续留在缓存里,避免因为一次读不全导致解析失败
  • 命令校验:严格检查开头结尾、字段数量、载荷长度,保证只处理合法的命令
  • JSON解析:把载荷转成Python字典,方便后续操作
  • 命令执行:execute_command函数里可以根据不同的命令类型(比如你的SEND)添加自定义的业务逻辑

注意事项

  1. 确保串口参数和嵌入式系统一致:波特率115200,数据位8,停止位1,无校验(默认就是这个配置,如果你的系统有修改,要在serial.Serial里加对应的参数)
  2. 处理异常:代码里加了串口打开失败、JSON解析错误、键盘中断等异常处理,避免程序崩溃
  3. 调试建议:如果遇到解析问题,可以在代码里加打印,输出原始的buffer内容,排查数据是否正确

内容的提问来源于stack exchange,提问作者Federico

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:16:37