bsb036 2024-02-27 18:32 采纳率: 43.8%
浏览 5
已结题

串口通信传输字符的质量控制

利用ChatGPT设计了两个通过串口收发信息的程序,接收端在收到信息后,将信息拆解再插入数据库,目前在串口通信时,一条100余字节的信息,第一次发送时只会接收到信息的1/3,第二次发送时,接收到第一次发送信息的后2/3和第二次的1/3组合,第三次又是第二次的2/3和第三次的1/3组合,以此类推。
实际使用中会发送至少100-200字符的信息,请教如何做到接收信息的完整。以下为发送端的部分代码:

def send_data(self):
        try:
            # 获取勾选项状态
            selected_options = [option for option, var in self.options.items() if var.get() == 1]
        
            # 获取单选项内容
            alert_type = self.alert_type_var.get()
        
            # 获取填写项内容
            author = self.author_var.get()
        
            # 获取当前时间
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
        
            # 获取文本编辑框内容
            message = self.text_box.get("1.0", tk.END)
        
            # 构建数据字符串
            data_to_send = f"Tables: {', '.join(selected_options)} | EventKind: {alert_type} | Event: {message} | team: 清风班组 | Writer: {author} | DT: {current_time} | subKind: 其他 | MSG_From: QX2 | ENDHERE"
    
            # 调用串口通信实例的 send_data 方法发送数据
            self.serial_communicator.send_data(data_to_send)
            
            print("Sending data:", data_to_send)

        except Exception as e:
            print(f"Error sending data: {e}")

接收端的代码:

    def receive_data(self):
        while True:
            try:
                if self.serial_communicator and self.serial_communicator.is_open:
                    # 清空队列中的旧数据
                    with self.receive_queue.mutex:
                        self.receive_queue.queue.clear()
                    # 从串口读取数据
                    received_data = self.serial_communicator.readline().decode('utf-8')
                    # 判断是否包含结束符号
                    if 'ENDHERE' in received_data:
                        # 找到结束符号时,截取到结束符号之前的部分
                        received_data = received_data.split('ENDHERE')[0]                    
                    print(received_data)
    
                    # 将接收到的数据放入队列
                    self.receive_queue.put(received_data)
    
                    # 立即处理接收到的数据
                    self.process_received_data()
    
            except Exception as e:
                print(f"Error receiving data: {e}")

  • 写回答

13条回答 默认 最新

  • 专家-郭老师 Java领域新星创作者 2024-02-27 18:33
    关注

    🌈🌈🌈参考通义千问和郭老师的小迷弟雅思莫了-编写提供🌈🌈🌈
    您可以参考如下,如果回答的不正确,及时评论区回复我,我会根据你错误描述追加回复,直到您满意为止。

    看起来你的程序在处理接收到的数据时存在问题,你提到数据被“拆片”接收,这个现象非常像是使用串行通讯时的一种常见问题,那就是数据分块。当发送方连续快速发送大量数据时,接收方可能会在任何字节间隔接收到这些数据,这是由于物理层异步串行通信的特性决定的。为了解决这个问题,通常我们需要在应用层做一些处理。
    这里有一个可能的解决方案,可以尝试调整你的接收代码如下:

        def receive_data(self):
            received_data = ""  // 初始化接收数据的字符串
            while True:
                try:
                    if self.serial_communicator and self.serial_communicator.is_open:
                        # 从串口读取一行数据
                        received_data += self.serial_communicator.readline().decode('utf-8')
                        # 判断是否包含结束符号
                        if 'ENDHERE' in received_data:
                            # 找到结束符号时,截取到结束符号之前的部分,并清空接收数据字符串
                            data_to_process = received_data.split('ENDHERE')[0]
                            received_data = ""
                            print(data_to_process)
    
                            # 将接收到的数据放入队列
                            self.receive_queue.put(data_to_process)
    
                            # 立即处理接收到的数据
                            self.process_received_data()
    
                except Exception as e:
                    print(f"Error receiving data: {e}")
    
    
    

    在这个修正版本的receive_data方法中,received_data被改为一个持久变量,它不会在每次循环开始时被重置。每次从串口收到数据时,数据都会被添加到received_data变量中,而不是替换它。如果在received_data中找到了ENDHERE字符串,那么数据被拆分,一部分数据被取出来处理,剩余的数据留在received_data中,等待接收进一步的数据。这样,即使你的数据在多次readline()调用中被分割,你的程序也能正确地处理这些数据。

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

报告相同问题?

问题事件

  • 系统已结题 3月9日
  • 已采纳回答 3月1日
  • 创建了问题 2月27日

悬赏问题

  • ¥15 Stata链式中介效应代码修改
  • ¥15 latex投稿显示click download
  • ¥15 请问读取环境变量文件失败是什么原因?
  • ¥15 在若依框架下实现人脸识别
  • ¥15 添加组件无法加载页面,某块加载卡住
  • ¥15 网络科学导论,网络控制
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错