C#中使用seriport和单片机进行串口长数据收发不全,解决办法

最近做了一个项目,上位机向单片机要205个字节的报文。每次上位机接收的数据总是分成好几段,不能一次接收205个字节。所以对数据处理造成影响。因此就想着怎么能实现一次接收205字节数据,一次进行处理。试了很多办法,最后终于解决了。

C#中,使用的是serialPort.DataReceived来接收数据。一开始,上位机向单片机发送轮询指令后,单片机按照modbus协议上传205个字节数据。但是每次上位机将数据分成32个字节一段的形式接收。找了半天原因,最终发现,由于计算机速度很快,但是单片机发送205个字节数据是有一个过程的。然而,上位机收到一个字节就会触发serialPort.DataReceived,这时上位机去读接收缓冲区时,时间刚好只能读取32个字节。所以,我在接收一开始进行了延时,使用了 System.Threading.Thread.Sleep(300);延时300后,发现一次能够完整的接收205个字节数据。

分析了一下,原因可能是上位机接收完205个字节需要的时间在300毫秒,如果不延时,直接去读的话,只能读到目前接收的32个字节。具体看程序吧!

/// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void serialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                //***正在接收状态指示。
                IsReceving = true;  
                //等待所有数据全部进入缓冲区
                System.Threading.Thread.Sleep(300);
                
                //读入收到的数据。
                int Len = serialport.BytesToRead;
                if (Len < 1)
                {
                    //***接收完成状态指示。
                    IsReceving = false;  
                    return;
                }


                byte[] data = new byte[Len];
                serialport.Read(data, 0, Len);
                
                //字符串处理。
               string Str = Encoding.GetEncoding("GB2312").GetString(data);


                //数据转十六进制字符串。
                string Hex = string.Empty;
                for (int i = 0; i < data.Length; i++)
                {
                    string tempstr = Convert.ToString(data[i], 16);
                    if (tempstr.Length < 2)
                    {
                        tempstr = '0' + tempstr;
                    }
                    Hex += tempstr + ' ';
                }
                Hex = Hex.ToUpper();


                //使用委托跨线程读取数据。
                rtbxRecStr.Invoke(new EventHandler(delegate
                {
                    //***正在处理字符串。
                    DoingStr = true;


                    rtbxRecStr.AppendText(Str);
                    if (chkbxAutoClr.Checked && rtbxRecStr.Text.Length > 10000)
                    {
                        rtbxRecStr.Text = string.Empty;
                    }
                    //将控件的内容滚动到当前位置。
                    rtbxRecStr.ScrollToCaret();
                    //***完成处理字符串。
                    DoingStr = false;
                }
                ));
               // Logger.Debug(string.Format("接收数据: {0}", Str));


                rtbxRecHex.Invoke(new EventHandler(delegate
                {
                    //***正在处理十六进制数据。
                    DoingHex = true;


                    rtbxRecHex.AppendText(Hex);
                    if (chkbxAutoClr.Checked && rtbxRecHex.Text.Length > 10000)
                    {
                        rtbxRecHex.Text = string.Empty;
                    }
                    //将控件的内容滚动到当前位置。
                    rtbxRecHex.ScrollToCaret();
                    //***完成处理十六进制数据。
                    DoingHex = false;
                }
                ));
                Logger.Debug(string.Format("接收数据: {0}", Hex));


                while (DoingStr || DoingHex)
                {
                    //处理串口接收事件及其它系统消息。
                    Application.DoEvents();
                }
                //***接收完成状态指示。
                IsReceving = false;                
            }
            catch (Exception Err)
            {
                MessageBox.Show(Err.Message, "串口调试助手");
            }
        }


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值