zoukankan      html  css  js  c++  java
  • c#串口通信并处理接收的多个参数

    最近摸索做个上位机,简单记录一下关键的几个部分

    c#做串口通信主要使用的是System.IO.Ports类,其实还是十分方便的
    最终效果如下:

    千万不要忘记了下面这个

    填写串口相关配置

    我们可以通过GetPortNames方法获取本机的端口列表,注意:不同设备连接电脑后端口不一定相同

    string[] sps = SerialPort.GetPortNames();
    

    配置其他串口相关
    例如波特率列表

    string[] baud = { "300", "1200", "2400", "4800", "9600", "19200", "38400", "57600" };
    comboBox2.Items.AddRange(baud);     //添加波特率列表
    

    打开串口

    其实主要就是用当前串口属性判断是否是打开状态

    private void Button1_Click(object sender, EventArgs e)
            {
                //trycatcj处理串口打开过程中的异常
                try
                {
                    //将可能产生异常的代码放置在try块中
                    //根据当前串口属性来判断是否打开
                    if (serialPort1.IsOpen)
                    {
                        //串口已经处于打开状态
                        serialPort1.Close();    //关闭串口
                        button1.Text = "打开串口";
                        button1.BackColor = Color.ForestGreen;
                        comboBox1.Enabled = true;
                        comboBox2.Enabled = true;
                        comboBox3.Enabled = true;
                        comboBox4.Enabled = true;
                        comboBox5.Enabled = true;
                       ReceptTb.Text = "";  //清空接收区
                        SendTb.Text = "";     //清空发送区
                    }
                    else
                    {
                        //串口已经处于关闭状态,则设置好串口属性后打开
                        comboBox1.Enabled = false;
                        comboBox2.Enabled = false;
                        comboBox3.Enabled = false;
                        comboBox4.Enabled = false;
                        comboBox5.Enabled = false;
                        serialPort1.PortName = comboBox1.Text;
                        serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                        serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);
    
                        if (comboBox4.Text.Equals("None"))
                            serialPort1.Parity = System.IO.Ports.Parity.None;
                        else if (comboBox4.Text.Equals("Odd"))
                            serialPort1.Parity = System.IO.Ports.Parity.Odd;
                        else if (comboBox4.Text.Equals("Even"))
                            serialPort1.Parity = System.IO.Ports.Parity.Even;
                        else if (comboBox4.Text.Equals("Mark"))
                            serialPort1.Parity = System.IO.Ports.Parity.Mark;
                        else if (comboBox4.Text.Equals("Space"))
                            serialPort1.Parity = System.IO.Ports.Parity.Space;
    
                        if (comboBox5.Text.Equals("1"))
                            serialPort1.StopBits = System.IO.Ports.StopBits.One;
                        else if (comboBox5.Text.Equals("1.5"))
                            serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
                        else if (comboBox5.Text.Equals("2"))
                            serialPort1.StopBits = System.IO.Ports.StopBits.Two;
    
                        serialPort1.Open();     //打开串口
                        button1.Text = "关闭串口";
                        button1.BackColor = Color.Firebrick;
             
                        this.Activate();
                    }
                }
                catch (Exception ex)
                {
                    //捕获可能发生的异常并进行处理
    
                    //捕获到异常,创建一个新的对象,之前的不可以再用
                    serialPort1 = new System.IO.Ports.SerialPort();
                    //刷新COM口选项
                    comboBox1.Items.Clear();
                    comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
                    //响铃并显示异常给用户
                    System.Media.SystemSounds.Beep.Play();
                    button1.Text = "打开串口";
                    button1.BackColor = Color.ForestGreen;
                    MessageBox.Show(ex.Message);
                    comboBox1.Enabled = true;
                    comboBox2.Enabled = true;
                    comboBox3.Enabled = true;
                    comboBox4.Enabled = true;
                    comboBox5.Enabled = true;
                }
            }
    

    消息传送

    这个也没有太多特别的,只要调用Write方法即可

     private void SendBtn_Click(object sender, EventArgs e)
            {
                try
                {
                    Console.WriteLine(serialPort1.IsOpen);
                    //首先判断串口是否开启
                    if (serialPort1.IsOpen)
                    {
                        //串口处于开启状态,将发送区文本发送
                        serialPort1.Write(SendTb.Text);
                        SendTb.Text = "";
                    }
                }
                catch (Exception ex)
                {
                    //捕获到异常,创建一个新的对象,之前的不可以再用
                    serialPort1 = new System.IO.Ports.SerialPort();
                    //刷新COM口选项
                    comboBox1.Items.Clear();
                    comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
                    //响铃并显示异常给用户
                    System.Media.SystemSounds.Beep.Play();
                    button1.Text = "打开串口";
                    button1.BackColor = Color.ForestGreen;
                    MessageBox.Show(ex.Message);
                    comboBox1.Enabled = true;
                    comboBox2.Enabled = true;
                    comboBox3.Enabled = true;
                    comboBox4.Enabled = true;
                    comboBox5.Enabled = true;
                }
            }
    

    以上的几个基本功能其实只要调用方法再加上处理异常即可

    接收消息

    这个接收消息就非常灵活了,说简单简单,说难也有点难,如果要求不高,只是为了展示出接收的消息,的确可以有很简单的方法

    这是最简单的方法,只是单纯的将缓存区得到的字符拼接在一起,但是如果传进来的数据不只一类,我们需要将其中每一种分离出来,这种及时从缓存区取出来并拼接在一起就不太适用了,因为从缓存区取出的字符不一定是完整的

    String str = serialPort1.ReadExisting();
    

    因此,我求助于搜索引擎,了解到要解决这个问题,我们需要先将得到的字符放在缓存区中,等缓存区积攒了一定的字符再进行读取,每次提取一定的字符后,清空缓存区,将我拿到的这一串字符,转换为数组,我这个例子中有三个参数x y z,我就是将三个参数从下位机中按顺序传入,然后接收的时候以逗号作为分隔符进行拆分(我在单片机上发送消息的时候就用逗号分隔参数了),那么按顺序我们得到的数据就是x1,x2,x3···那么我们只要记录下现在处理的是哪个参数就可以按需处理了。
    但是依然有不能解决的问题,就是若频率过高,处理的速度就跟不上了,但是现实情况中并不是每几毫米调用一次,所以我觉得这个问题也可以忽略不计

            private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
            {
                try
                {
                    //因为要访问UI资源,所以需要使用invoke方式同步ui
                    this.Invoke((EventHandler)(delegate
                    {
                      
                        int byteNumber = serialPort1.BytesToRead;
    
                        Thread.Sleep(20);
    
    
                        //延时等待数据接收完毕。
                        while ((byteNumber < serialPort1.BytesToRead) && (serialPort1.BytesToRead < 77))
                        {
                            byteNumber = serialPort1.BytesToRead;
                            Thread.Sleep(20);
    
                        }
                        int n = serialPort1.BytesToRead; //记录下缓冲区的字节个数 
    
                        //Console.WriteLine("n" + n);
                        byte[] buf = new byte[n]; //声明一个临时数组存储当前来的串口数据 
                        serialPort1.Read(buf, 0, n); //读取缓冲数据到buf中,同时将这串数据从缓冲区移除 
                        string str = System.Text.Encoding.Default.GetString(buf);
                        string[] strArray = str.Split(',');
                        
    
                        int count = 0;
                        for (int i = 0; i < strArray.Length; i++)
                        {
                            if(count == 0)
                            {
                                textBox1.Text = strArray[i];
                            }else if(count == 1)
                            {
                                textBox2.Text = strArray[i];
                            }else if(count == 2)
                            {
                                textBox3.Text = strArray[i];
                            }
                            count++;
                            if(count == 3)
                            {
                                count = 0;
                            }
    
                        }
    
    
    
    
                    }
                       )
                    );
    
                }
                catch (Exception ex)
                {
                    //响铃并显示异常给用户
                    System.Media.SystemSounds.Beep.Play();
                    MessageBox.Show(ex.Message);
    
                }
            }
    

    那么下一步是为其添加上一个视频面板以及遥控手柄,加油继续学习

    参考来源:https://www.cnblogs.com/Mculover666/p/9128906.html

  • 相关阅读:
    spring boot SpringApplication.run 执行过程
    算法 计算四则运算字符串结果
    算法 RingBuffer
    java BigDecimal 四舍五入
    算法 常用函数和近似
    java 多线程执行
    Java 三个线程依次输出ABC
    Java interrupt 中断
    java 垃圾收集器与内存分配策略
    软件项目与软件产品的区别
  • 原文地址:https://www.cnblogs.com/yuyuan-bb/p/10961755.html
Copyright © 2011-2022 走看看