一个简单的串口通讯程序

····从2015年到现在,将近4年没有写程序了,这次是一个朋友要我做物联网的项目,要学习一些新东西,做起来再说。

····基于STM32的通讯调试起来还是不方便,用C#写了一个简单的收发程序,先模拟链式收发,主要是测试流程是否正常无误。后面用C写好这部分处理程序再下载到单片机上就OK了,可能是刚开始接触STM32的单片机不习惯,还是觉得这样省事。

····在用C#写的时候,发现关闭端口出现死机现象,到网上百度也没有找到好的处理办法,最终还是用委托注销的方式解决了。

····主要代码:

        private void sp_DataReceived(object sender,SerialDataReceivedEventArgs e)
        {

            System.Threading.Thread.Sleep(500);//延时500ms等待接收完数据
            Application.DoEvents();
            this.BeginInvoke((EventHandler)(delegate
            {
                if (IsOpen)
                {
                    textBox2.Text += "\r\n新接收到的数据:"+Convert.ToString(DateTime.Now);
                    if (IsFormatHex == false)
                    {
                        byte[] ReceiveData = new byte[sp.BytesToRead];//创建接收字节数组
                        sp.Read(ReceiveData, 0, ReceiveData.Length);//读取接收到的数据
                        receiveDatas.Clear();
                        receiveDatas.AddRange(ReceiveData);

                        textBox2.Text += Encoding.Default.GetString(receiveDatas.ToArray());
                        //textBox2.Text += sp.ReadLine().ToString();

                        //存入本地数据库
                        FFDWTable SaveFFDW = new FFDWTable();
                        SaveFFDW.sCommType = "WS";
                        SaveFFDW.sCommPara = "命令参数";
                        SaveFFDW.sSend = "01";
                        SaveFFDW.dtSendTime = DateTime.Now;
                        SaveFFDW.sRece = "02";
                        SaveFFDW.sData = Encoding.Default.GetString(receiveDatas.ToArray());
                        //SaveData(SaveFFDW);
                        

                    }
                    else
                    {

                        Byte[] ReceivedData = new Byte[sp.BytesToRead];//创建接收字节数组
                        sp.Read(ReceivedData, 0, ReceivedData.Length);//读取接收的数据
                        String ReceDataText = null;
                        for (int i = 0; i < ReceivedData.Length - 1; i++)
                        {
                            ReceDataText += ("0x" + ReceivedData[i].ToString("X2" + " "));
                        }
                        textBox2.Text += ReceDataText;
                    }
                    sp.DiscardInBuffer();//丢弃接收缓冲区数据

                }

            }));

        }

····上面是接收事件,主要处理接收到的数据。

····在打开串口设置属性的时候,要注册事件:

            //定义DataReceived事件,当串口收到数据后触发事件
           sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

····在关闭串口的时候,避免死机的方法:

                    try
                    {
                        // 消除委托
                        if (IsOpen == false)
                        {
                            sp.DataReceived -= sp_DataReceived;
                        }
                        sp.Close();
                        IsSetProperty = false;
                        btOpenComPort.Text = "打开串口";
                        CBCommPort.Enabled = true;
                        CBBaudRate.Enabled = true;
                        CBDataBit.Enabled = true;
                        CBParitv.Enabled = true;
                        CBStopBit.Enabled = true;
                        rbChar.Enabled = true;
                        rbHex.Enabled = true;
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("关闭串口时发生错误!", "错误提示");
                    }

一个简单的串口通讯程序_第1张图片

  经过试验,如果是BeginInvoke则不会死机,换成Invoke则死机,在网上查了资料,原来BeginInvoke是采用异步方式来处理里面的委托,而Invoke采用的是同步方式,它在处理完事务期间对其他消息有阻塞,所以造成了死机。

你可能感兴趣的:(C#)