有回响的山谷 2023-01-11 16:30 采纳率: 57.1%
浏览 56
已结题

C#串口通讯接收数据的处理

目前在使用C#编写上位机串口通讯界面,需要实现对下位机的通知
在处理接收数据时,现在遇到的一些,请各位多多指导一下
问题1.我在根据自定义协议里面的内容,已经实现数据的接收,在处理数据时,不知道如何设置发送间断判断
我一帧数据是64位字节,该怎么实现:到达指定长度,将整包数据交给下一级处理,然后重新开始包头的查找
问题2。我程序一运行,上位机界面在接收到数据后就卡顿,无法对界面进行操作,发现是我接收函数设计的是一边读数据,一边写数据,所以卡顿,想问该怎么设置读与写分开操作

代码如下: 图片中为数据处理内容,框框中是问题1缺少的内容

 private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while(true)
            {
                if (!sp.IsOpen)
                {

                System.Threading.Thread.Sleep(200);
                sp.DiscardInBuffer();//丢弃接收缓冲区数据
            }
            else
            {
                try
                {
                    Thread.Sleep(20);
                    Listening = true;
                    this.Invoke((EventHandler)(async delegate
                    {
                        byte[] readbuff = null;
                        int readBuffer = sp.BytesToRead;//实际接收到的字节数
                        if (readBuffer == 0)
                        {
                            return;
                        }
                        byte[] buf = new byte[readBuffer]; //创建临时接收字节数组
                        string RecvDataText = null;    //显示字符存储
                        sp.Read(buf, 0, readBuffer);  //读取所有接收到的数据
                        resetEvent.Set();
                        recv_count += readBuffer;
                        if (isHex == false)//如果接收模式为字符模式
                        {
                            String decodedString = Encoding.Default.GetString(buf); //设置编码格式,显示汉字                                
                            tbxRecvData.Text += decodedString + " "; //接收框显示,追加数据  
                        }
                        else//如果接收模式为HEX数值模式
                        {
                            for (int i = 0; i < readBuffer; i++)
                            {
                                RecvDataText += ("0x" + buf[i].ToString("X2") + " "); //显示前缀0x
                            }
                            tbxRecvData.Text += RecvDataText;
                        }
                        //缓存数据
                        buffer.AddRange(buf);
                        int index = 0;
                        //完整性判断
                        while (buffer.Count >= 64)//完整一帧数据;
                        {//查找数据头
                            if (buffer[index] == 0xAA && buffer[index+1] == 0x55)//传输数据有帧头,用于判断 
                            {
                                index = buffer[index+3];
                                if (buffer.Count < index + 64)
                                {//数据未接收完整跳出循环
                                    break;
                                }
                                readbuff = new byte[index + 64];
                                //得到完整的数据,复制到readbuff中 
                                buffer.CopyTo(0, readbuff, 0, index + 64);
                                //从缓冲区中清除
                                buffer.RemoveRange(0, index + 64);
                                HandData?.Invoke(readbuff);
                                Thread.Sleep(20);
                                
                            }
                            else//开始标记或版本号不正确时清除
                            {
                                buffer.RemoveAt(0); 
                                return;
                            }
                        }
                        await Task.Delay(20);         
                    }));
                }
                finally
                {
                    recv_count = 0;
                    Listening = false;//我用完了,ui可以关闭串口了。 
                }
            }    
        }
        
    }

img

  • 写回答

2条回答 默认 最新

  • 於黾 2023-01-11 16:44
    关注

    1.你设置一个byte[]全局变量,接收到数据就循环往里面塞,塞够64个就处理一下
    当然用list会更好,这样如果是从一半开始接收的,可以把前面的remove掉,只保留有效的部分,处理完就clear
    用数组你需要额外的索引来判断数组塞了多少个数据了,而用list你可以直接判断length
    2.卡顿跟你同时读写没有关系,问题是你的IO占用了主线程,而界面重绘和鼠标键盘响应也在主线程里,主线程不干活了肯定卡顿呀
    你需要用多线程技术,这里有很多种办法,比如自己建立个线程,比如直接拖个backgroundworker出来作为工作线程,比如使用异步发送接收


    可以看看我之前写的一个例子,以前是免费的,现在需要积分了,这个积分我每次改掉它都会给我自动变回49,似乎最低只能49

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

报告相同问题?

问题事件

  • 系统已结题 1月19日
  • 已采纳回答 1月11日
  • 创建了问题 1月11日

悬赏问题

  • ¥100 微信小程序跑脚本授权的问题
  • ¥100 房产抖音小程序苹果搜不到安卓可以付费悬赏
  • ¥15 STM32串口接收问题
  • ¥15 腾讯IOA系统怎么在文件夹里修改办公网络的连接
  • ¥15 filenotfounderror:文件是存在的,权限也给了,但还一直报错
  • ¥15 MATLAB和mosek的求解问题
  • ¥20 修改中兴光猫sn的时候提示失败
  • ¥15 java大作业爬取网页
  • ¥15 怎么获取欧易的btc永续合约和交割合约的5m级的历史数据用来回测套利策略?
  • ¥15 有没有办法利用libusb读取usb设备数据