天天看点

C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)

这节介绍实现的是利用SerialPort类进行串口的链接。

.Net Framework 作为微软开发的一个框架,万变不离其宗,要怎么使用一个东西,就最好看它的说明书 。   

SerialPort Class 的文档链接:https://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport?view=netframework-4.5

它的示例介绍写着:

The following code example demonstrates the use of the SerialPort class to allow two users to chat from two separate computers connected by a null modem cable. In this example, the users are prompted for the port settings and a username before chatting. Both computers must be executing the program to achieve full functionality of this example.

提取重点就是:两个计算机的users 通过使用SerialPort class 去进行聊天 ,两个电脑通过的是a null modem cable(这里应该指的是串口线,因为RS232线的名字是RS232 Cable (Null Modem Cable))进行连接。

我们现阶段主要实现的从串口中获取数据,写数据暂时不需要,所以我们可以在里面提取我们需要的部分。

在文档的左侧,我们可以选择其方法和事件来选择我们所需要的实例。

C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)
C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)

 选取事件中的DataReceived,我们这次所需要的,其实例代码:

using System;
using System.IO.Ports;

class PortDataReceived
{
    public static void Main()
    {
        SerialPort mySerialPort = new SerialPort("COM1");

        mySerialPort.BaudRate = 9600;
        mySerialPort.Parity = Parity.None;
        mySerialPort.StopBits = StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = Handshake.None;
        mySerialPort.RtsEnable = true;

        mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        mySerialPort.Open();

        Console.WriteLine("Press any key to continue...");
        Console.WriteLine();
        Console.ReadKey();
        mySerialPort.Close();
    }

    private static void DataReceivedHandler(
                        object sender,
                        SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Console.WriteLine("Data Received:");
        Console.Write(indata);
    }
}
           

可以看到,微软的实例很清楚的向我们展示了需要初始化的内容和SerialDataReceivedEventHandler的使用,有兴趣的可以先体验实现一下,然后我们看一下我们程序里面使用的版本。 

看一下界面:

C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)

 界面实现,两个 comboBox,DropDownStyle选择DropDownList只允许选不允许修改,然后通过button进行触发(打开/关闭)。comboBox的数据项自己设计,串口这里就可以利用SerialPort.GetPortNames()来获取电脑的串口。

串口comboBox实现代码:

private void Com_comboBox_Click()
{
   string[] portNamesArray = SerialPort.GetPortNames();
   this.Com_comboBox.Items.Clear();
   foreach (var item in portNamesArray)
    {
       this.Com_comboBox.Items.Add(item);
    }
       this.Com_comboBox.Items.Add("");
}
           

 波特率就没什么实现代码啦,数据项我是写了几个常用在item里面了。

(因为停止位什么的都是写死的,所以直接用Label写死)

然后就是按钮的实现代码,里面主要是对串口的初始化和打开 :

private void Com_btn_Click(object sender, EventArgs e)
        {
            if (!com.IsOpen)
            {
                try
                {
                    string serialName = Com_comboBox.SelectedItem.ToString();
                    com.PortName = serialName;
                    string strBaudRate = Bps_comboBox.SelectedItem.ToString();
                    Int32 iBaudRate = Convert.ToInt32(strBaudRate);

                    com.BaudRate = iBaudRate;
                    com.Parity = Parity.None;//无奇偶校验位
                    com.StopBits = StopBits.One;//1个停止位
                    com.Handshake = Handshake.RequestToSend;//控制协议
                    com.ReceivedBytesThreshold = 13;//设置 DataReceived 事件发生前内部输入缓冲区中的字节数

                    com.Handshake = Handshake.RequestToSend;//握手协议:RTS硬件流控制
                    com.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

                    if (com.IsOpen == true)
                    {
                        com.Close();
                    }
                    com.Open();
                    Com_btn.Text = "关闭串口";

                }
                catch (Exception ex)
                {
                    MessageBox.Show("错误信息:" + ex.Message + "!");
                    return;
                }
            }
            else
            {
                com.Close();
                Com_btn.Text = "打开串口";
            }
        }
           

DataReceivedHandler的代码:

void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                if (com.IsOpen)
                {
                    try
                    {

                        TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);//自己加的延时
                        Thread.Sleep(waitTime);
                        string str = "";//接收的字符串
                        int count = com.BytesToRead;

                        byte[] readBuffer = new byte[count];//byte
                        com.Read(readBuffer, 0, count);

                        foreach (byte item in readBuffer)
                        {
                            str += Convert.ToChar(item);//byte[] to char ->string
                        }


                        com.DiscardOutBuffer();//outBuffer
                        if (count != 0)
                        {
                            //线程里不可以直接对UI进行赋值
                            this.Invoke(new System.Threading.ThreadStart(delegate ()
                            {
                                
                               /*
                                    这里可以更新UI
                                */
                                }
                            }));
                        }
                    }
                    catch (TimeoutException) { }
                }
                else
                {
                    TimeSpan waitTime = new TimeSpan(0, 0, 0, 0, 50);
                    Thread.Sleep(waitTime);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("错误信息:" + ex.Message + "!");
            }
        }
           

(这里转换数据的方法网上五花八门,而且有的还有些乱码什么的,踏了不少坑还是微软的文档比较省事) 

我用的是读取字节,再转成char再拼接成字符串,好像Read可以直接接收Char字符,可以把处理数据那里改成:

// Read (char[] buffer, int offset, int count);
   char[] readBuffer = new char[count];
   com.Read(readBuffer, 0, count);
   foreach (char item in readBuffer)
     {
        str += item;
     }
           
C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)

 SerialPort类到此就介绍完成了,完成到这里,你的项目已经具备了连接串口、接收数据的功能了(更新UI的代码在更新Ui章节贴出)。

自备串口助手这个就不用说了,除此之外建议大家安装一个虚拟串口工具,在大家没有连接硬件的情况下,通过串口助手发送数据,也能进行测试。

我用的是Configure Virtual Serial Port Driver,添加端口就能用,一个发一个收,还挺好用的。

C#winform小demo-串口传输实现硬件数据回传(SerialPort类使用)

下一节介绍Chart图表的应用。