串口输入缓冲区历史数据干扰问题 python的解决方案

串口输入缓冲区历史数据干扰问题 python的解决方案,非常简单
 加上这行代码就行self.serial.reset_input_buffer()

下面详细介绍

问题分析

接收数据包含历史残留的原因是:串口接收缓冲区中未及时清理的历史数据与新响应混合。Modbus RTU 协议基于时序传输,若在发送新指令前未清空缓冲区,会导致残留数据被误读。

解决方案

在发送新命令前清空串口输入缓冲区,确保只读取当前命令的响应。

修改代码步骤
  1. 在发送命令前清空输入缓冲区
    在 general_send_and_rec_modbus_06 方法的发送逻辑前添加 self.serial.reset_input_buffer()

python

def general_send_and_rec_modbus_06(self, 
                               device_address,
                               register_addr,
                               value,
                               function_code=0x06):
    """组合命令生成与发送的整合方法"""
    try:
        # ... [参数校验和命令构造部分保持不变] ...

        # ========== 发送部分 ==========
        if not hasattr(self, 'serial') or not self.serial.is_open:
            messagebox.showwarning("警告", "请先打开串口")
            return

        # 清空输入缓冲区,避免历史数据干扰
        self.serial.reset_input_buffer()

        # 发送当前命令
        self.serial.write(message)

        # ... [后续格式化显示和接收逻辑保持不变] ...
        self.receive_data()  # 调用接收方法

    except Exception as e:
        messagebox.showerror("错误", f"操作失败: {str(e)}")
  1. 优化接收逻辑(可选)
    Modbus RTU 的响应长度与功能码相关,例如:

    • 功能码 0x03(读寄存器):响应长度 = 5 + 2*寄存器数量(字节)。

    • 功能码 0x06(写单个寄存器):固定响应长度 8 字节(包含 CRC)。

    可改进 receive_data 方法,根据功能码动态判断数据完整性:

python

def receive_data(self):
    self.serial.timeout = 1  # 设置超时时间
    received_data = b""
    start_time = time.time()
    
    while True:
        # 超时退出循环
        if time.time() - start_time > self.serial.timeout:
            break
        
        # 读取当前缓冲区所有数据
        new_data = self.serial.read(self.serial.in_waiting or 1)
        if new_data:
            received_data += new_data
            
            # 根据Modbus协议判断数据完整性(示例以功能码0x03和0x06为例)
            if len(received_data) >= 2:
                function_code = received_data[1]
                if function_code == 0x03:
                    # 检查数据长度:地址(1) + 功能码(1) + 字节数(1) + 数据(2*N) + CRC(2)
                    byte_count = received_data[2]
                    expected_length = 5 + byte_count
                    if len(received_data) >= expected_length:
                        break
                elif function_code == 0x06:
                    # 固定长度:地址(1) + 功能码(1) + 寄存器地址(2) + 数据(2) + CRC(2) = 8字节
                    if len(received_data) >= 8:
                        break
    
    # 显示接收数据
    if received_data:
        hex_data = ' '.join(f"{b:02X}" for b in received_data)
        self.receive_text.insert(tk.INSERT, f"接收的数据: {hex_data}\n")
    else:
        self.receive_text.insert(tk.INSERT, "接收回复报文: 无数据接收\n")

你可能感兴趣的:(python,单片机,开发语言)