魚琦琦 2024-04-29 13:19 采纳率: 100%
浏览 28
已结题

树莓派串口读取stm32发过来的数字报错

img


这段报错有时候会出现,有时候又没问题。我该如何避免这种情况的发生?树莓派先启动程序,stm32后开机,一开机就会出现这个报错,可是这个时候stm32并未给树莓派发送任何串口数据,树莓派就直接报错了。有时候32开机就正常的,树莓派程序没有报错,串口接受正常

  • 写回答

12条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-04-29 13:19
    关注

    引自免费微信小程序:皆我百晓生

    从你提供的信息来看,错误发生在尝试将接收到的数据从字节流解码为UTF-8编码的字符串时。错误提示UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 8: invalid start byte说明接收到的数据中包含了不兼容UTF-8编码的字节。

    要解决这个问题,可以采取以下几个步骤:

    1. 确定STM32发送的数据格式

    首先确认STM32发送的数据的确切格式。如果STM32发送的是纯数字或者特定的二进制数据,并非预期的文本(特别是如果它包含控制字符或非标准ASCII字符),直接使用UTF-8解码自然会出错。

    2. 使用更稳健的解码方式

    你可以尝试在解码时指定一个能容忍非UTF-8字符的错误处理策略,比如 'ignore''replace',这样即使遇到非法字节也能继续执行,而不是抛出异常。

    修改解码部分的代码如下:

    try:
        data = recv.decode('utf-8')  # 尝试用UTF-8解码
    except UnicodeDecodeError:
        data = recv.decode('utf-8', errors='ignore')  # 忽略解码错误
        # 或者
        # data = recv.decode('utf-8', errors='replace')  # 用特殊字符替换非法字节
    

    3. 确保串口初始化正确

    确保你的树莓派串口初始化设置与STM32发送端匹配,包括波特率、数据位、停止位和校验位等。

    4. 增加数据校验或同步机制

    如果可能,可以在STM32发送数据前加入特定的起始和结束标志,或者简单的协议头,让树莓派端在接收到有效数据包后再进行解码处理。例如,STM32发送<STX>数据<ETX>,其中<STX><ETX>是固定的控制字符,用于标识数据的开始和结束,树莓派端则在接收到这些标记后再尝试解码数据。

    5. 异常处理和重试逻辑

    增加对串口通信的异常处理和重试逻辑,确保在遇到临时错误时,程序能够恢复而不至于崩溃。

    示例代码段

    考虑上述建议,下面是一个简化的示例代码,展示如何改进数据接收处理过程:

    import serial
    import time
    import RPi.GPIO as GPIO
    
    # 初始化GPIO
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(37, GPIO.OUT)
    GPIO.setup(40, GPIO.OUT)
    
    # 串口初始化
    ser = serial.Serial('/dev/ttyAMA0', 9600)  # 根据实际情况调整串口号和波特率
    
    while True:
        try:
            # 读取一行数据,这里假设STM32发送完数据后会加上换行符
            recv = ser.readline()
            
            # 增加简单的数据有效性检查,例如期待数据以换行符结束
            if recv.endswith(b'\n'):
                try:
                    data = recv[:-1].decode('utf-8')  # 移除换行符再解码
                    print("Received:", data)
                    
                    # 根据解码后的数据执行相应操作
                    if data == "1":
                        print("播种2次")
                        # 其他操作...
                    elif data.isdigit():
                        value = int(data)
                        if value <= 50000:
                            GPIO.output(37, GPIO.LOW)
                        else:
                            GPIO.output(40, GPIO.HIGH)
                            time.sleep(0.1)  # 短暂保持高电平
                            GPIO.output(40, GPIO.LOW)
                except UnicodeDecodeError:
                    print("解码错误,忽略该数据包")
        except Exception as e:
            print("串口通信错误:", e)
            # 可以根据需要在这里增加重连或其他恢复逻辑
    
        # 根据实际情况调整循环等待时间
        time.sleep(0.1)
    

    注意事项

    • 确保STM32和树莓派的串口配置完全一致。
    • 上述代码中,我移除了原代码中的逻辑错误和未定义的变量引用,确保示例代码的清晰性。
    • 考虑到实际应用的复杂性,你可能需要根据具体情况调整代码细节。

    通过上述方法,应该能有效减少或避免因数据解码导致的异常,使程序运行更加稳定。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(11条)

报告相同问题?

问题事件

  • 系统已结题 5月8日
  • 已采纳回答 4月30日
  • 创建了问题 4月29日