C# WinForm下利用虚拟串口工具进行串口通信

发布时间 2023-05-05 16:04:15作者: 流纹

1、创建虚拟串口

虚拟串口工具的获取及使用:虚拟串口工具VSPD简单使用

2、创建WinForm应用程序

我这里使用的是vs2019

3、绘制WinForm窗体

 

界面确实不好看,不过这些都不重要
在这里说明一下用到了哪些控件及控件命名
1、接收数据及发送两个模块分别使用GroupBox容器控件包裹,发送部分容器命名gb_SendPanel,接口部分命名gb_ReceivePanel
2、接收栏内只有一个TextBox控件,命名为txt_Received,并设置属性允许多行,只读,显示垂直滚动条Multiline=true,ReadOnly = true,ScrollBars =Vertical
3、发送部分由6个文本Label,6个下拉框ComboBox,3个按钮Button,1个发送内容框TextBox组成
4、发送部分6个Label命名改不改都无所谓,后续不会再有用到
5、6个下拉框ComboBox分别命名为:串口下拉框cb_SelectComPort、波特率下拉框cb_baudSelect、停止位下拉框cb_StopSelect、数据位下拉框cb_DataSelect、检验位下拉框cb_CheckSelect、显示下拉框cb_DataShow
6、3个按钮Button命名分别为:检测串口btn_CheckPort、打开\关闭串口btn_OpenOrrEndCom、发送按钮btn_Send
7、发送内容文本框命名为txt_Send,设置属性允许多行Multiline = true
8、在这个窗体中字体上我这里是设置的宋体, 12pt(无关紧要)
9、窗体数据相关都是后台通过代码实现的,详情继续往下看

 4、属性初始化

     #region 初始话属性
        /// <summary>
        /// 实例化串口资源类
        /// </summary>
        private readonly System.IO.Ports.SerialPort serialPort = new System.IO.Ports.SerialPort();
        /// <summary>
        /// 波特率数值范围
        /// </summary>
        private readonly List<string> baudList = new List<string>() {
           "600","1200", "2400", "4800", "9600","14400", "19200", "28800","38400", "43000", "57600",
           "76800","115200","128000","230400","256000","460800","921600","1382400", "自定义"
        };
        /// <summary>
        /// 停止位
        /// </summary>
        private readonly List<string> stopList = new List<string> { "1", "1.5", "2" };
        /// <summary>
        /// 数据位
        /// </summary>
        private readonly List<string> dataList = new List<string> { "5", "6", "7", "8" };
        /// <summary>
        /// 校验位
        /// </summary>
        private readonly List<string> checkList = new List<string>() { "NONE", "ODD", "EVEN", "MARK", "SPACE" };
        /// <summary>
        /// 数据显示
        /// </summary>
        private readonly List<string> showList = new List<string>() { "16进制(HEX)", "字符显示(ASCII)" };
        #endregion
View Code

5、界面加载与控件初始化事件

    #region 界面加载
        /// <summary>
        /// 界面加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //串口选择
            InitPorts();
            //波特率
            InitBaud();
            //停止位
            InitStop();
            //数据位
            InitData();
            //校验位
            InitCheck();
            //初始化数据显示
            InitDataShow();
            //实例化串口控件
            InitSerialPort();
        }
        #endregion
        
        #region 初始化控件
        /// <summary>
        /// 初始化串口控件
        /// </summary>
        public void InitSerialPort()
        {
            serialPort.DataReceived += Sp1_DataReceived;//指示已通过由 System.IO.Ports.SerialPort 对象表示的端口接收了数据
            serialPort.DtrEnable = true;//获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号。
            serialPort.RtsEnable = true;//获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号
            serialPort.ReadTimeout = 1000;//设置数据读取超时为1s
            serialPort.Close();
        }
        /// <summary>
        /// 扫描可用串口,初始化串口选择
        /// </summary>
        public void InitPorts()
        {
            this.cb_SelectComPort.DropDownStyle = ComboBoxStyle.DropDownList;//禁用输入功能
            this.cb_SelectComPort.Items.Clear();//清除原有串口
            var comPostList = System.IO.Ports.SerialPort.GetPortNames().ToList();//读取串口
            if (comPostList != null && comPostList.Any())
            {
                comPostList = comPostList.OrderBy(x => x).ToList();
                foreach (var item in comPostList)
                {
                    this.cb_SelectComPort.Items.Add(item);
                }
                this.cb_SelectComPort.Text = comPostList.FirstOrDefault();//默认选择第一个串口
                this.cb_SelectComPort.Enabled = true;//打开选择框
            }
            else
            {
                MessageBox.Show("本机未找到串口!!!", "Error");
            }
        }
        /// <summary>
        /// 初始化校验位
        /// </summary>
        public void InitCheck()
        {
            this.cb_CheckSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in checkList)
            {
                this.cb_CheckSelect.Items.Add(item);
            }
            this.cb_CheckSelect.SelectedItem = "NONE";
        }
        /// <summary>
        /// 初始化数据位
        /// </summary>
        public void InitData()
        {
            this.cb_DataSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in dataList)
            {
                this.cb_DataSelect.Items.Add(item);
            }
            this.cb_DataSelect.SelectedItem = "8";
        }
        /// <summary>
        /// 初始化停止位
        /// </summary>
        public void InitStop()
        {
            this.cb_StopSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in stopList)
            {
                this.cb_StopSelect.Items.Add(item);
            }
            this.cb_StopSelect.SelectedItem = "1";
        }
        /// <summary>
        /// 初始化波特率
        /// </summary>
        public void InitBaud()
        {
            this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDownList;//不可手动输入
            foreach (var item in baudList)
            {
                this.cb_baudSelect.Items.Add(item);
            }
            this.cb_baudSelect.SelectedItem = "9600";
        }
        /// <summary>
        /// 初始化数据显示
        /// </summary>
        public void InitDataShow()
        {
            this.cb_DataShow.DropDownStyle = ComboBoxStyle.DropDownList;//不可手动输入
            foreach (var item in showList)
            {
                this.cb_DataShow.Items.Add(item);
            }
            this.cb_DataShow.SelectedItem = "字符显示(ASCII)";
        }
        #endregion
View Code

6、波特率选择事件

       /// <summary>
        /// 波特率选择,自定义时允许输入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb_baudSelect_SelectedValueChanged(object sender, EventArgs e)
        {
            if (this.cb_baudSelect.SelectedItem?.ToString() == "自定义")
            {
                this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDown;
            }
            else
            {
                this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            }
        }
View Code

7、检测串口

      /// <summary>
        /// 检测串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_CheckPort_Click(object sender, EventArgs e)
        {
            this.cb_SelectComPort.Items.Clear();//清除原有串口选择数据
            var comPostList = System.IO.Ports.SerialPort.GetPortNames().ToList();//读取串口
            if (comPostList != null && comPostList.Any())
            {
                comPostList = comPostList.OrderBy(x => x).ToList();//排序
                foreach (var item in comPostList)
                {
                    this.cb_SelectComPort.Items.Add(item);
                }
                this.cb_SelectComPort.Text = comPostList.FirstOrDefault();//默认选择第一个串口
            }
            else
            {
                MessageBox.Show("本机未找到串口!!!", "Error");
            }
        }
View Code

8、串口设置

    #region 设置串口
        /// <summary>
        /// 设置串口信息
        /// </summary>
        private void SetSerialPort()
        {
            string strBuadRate = this.cb_baudSelect.Text.Trim();
            string strDataRate = this.cb_DataSelect.Text.Trim();
            string strCheckRate = this.cb_CheckSelect.Text.Trim();
            string strPortRate = this.cb_SelectComPort.Text.Trim();
            string strStopRate = this.cb_StopSelect.Text.Trim();
            int IBaudBits = Convert.ToInt32(strBuadRate);
            int IDataBits = Convert.ToInt32(strDataRate);
            serialPort.PortName = strPortRate;//设置串口号
            serialPort.BaudRate = IBaudBits;//设置波特率
            serialPort.DataBits = IDataBits;//设置数据位
            serialPort.Encoding = Encoding.UTF8;
            //设置校验位
            switch (strCheckRate)
            {
                case "NONE":
                    serialPort.Parity = Parity.None;
                    break;
                case "ODD":
                    serialPort.Parity = Parity.Odd;
                    break;
                case "EVEN":
                    serialPort.Parity = Parity.Even;
                    break;
                case "MARK":
                    serialPort.Parity = Parity.Mark;
                    break;
                case "SPACE":
                    serialPort.Parity = Parity.Space;
                    break;
                default:
                    serialPort.Parity = Parity.None;
                    break;
            }
            //设置停止位
            switch (strStopRate)
            {
                case "1":
                    serialPort.StopBits = StopBits.One;
                    break;
                case "1.5":
                    serialPort.StopBits = StopBits.OnePointFive;
                    break;
                case "2":
                    serialPort.StopBits = StopBits.Two;
                    break;
                default:
                    serialPort.StopBits = StopBits.One;
                    break;
            }
            serialPort.ReadTimeout = 5000;//读取超时时间5s
        }
        #endregion
View Code

9、打开\关闭串口

       /// <summary>
        /// 打开\关闭串口按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_OpenOrrEndCom_Click(object sender, EventArgs e)
        {
            //串口是否打开
            if (!serialPort.IsOpen)
            {
                try
                {
                    this.btn_OpenOrrEndCom.Text = "关闭串口";
                    //如果打开状态,则先关闭一下
                    if (serialPort.IsOpen)
                    {
                        serialPort.Close();
                    }
                    //设置串口
                    SetSerialPort();
                    //打开串口后不允许更改连接属性
                    this.cb_baudSelect.Enabled = false;
                    this.cb_CheckSelect.Enabled = false;
                    this.cb_SelectComPort.Enabled = false;
                    this.cb_StopSelect.Enabled = false;
                    this.cb_DataSelect.Enabled = false;
                    //打开
                    serialPort.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("打开串口失败:" + ex.Message);
                    throw;
                }
            }
            else
            {
                this.cb_baudSelect.Enabled = true;
                this.cb_CheckSelect.Enabled = true;
                this.cb_SelectComPort.Enabled = true;
                this.cb_StopSelect.Enabled = true;
                this.cb_DataSelect.Enabled = true;
                this.btn_OpenOrrEndCom.Text = "打开串口";
                serialPort.Close();//关闭
            }
        }
View Code

10、发送与接收数据

       /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Send_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    byte[] sendData = null;
                    string send = this.txt_Send.Text.Trim();
                    var showText = this.cb_DataShow.Text;
                    //按照指定编码将string编程字节数组
                    byte[] b = Encoding.GetEncoding("GBK").GetBytes(send);
                    if (showText == "16进制(HEX)")
                    {
                        string result = string.Empty;
                        //逐字节变为16进制字符
                        for (int i = 0; i < b.Length; i++)
                        {
                            result += Convert.ToString(b[i], 16).ToUpper() + " ";
                        }
                        sendData = Encoding.GetEncoding("GBK").GetBytes(result);
                    }
                    else
                    {
                        sendData = b;
                    }
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {

                    MessageBox.Show("发送失败:" + ex.Message, "Error");
                }
            }
            else
            {
                MessageBox.Show("请先打开串口", "Error");
            }
        }
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //异步委托一个线程,不然接收数据时会出现数据线程错误
            this.Invoke((EventHandler)(delegate
            {
                var showText = this.cb_DataShow.Text;
                if (serialPort.IsOpen)
                {
                    try
                    {
                        byte[] receivedData = new byte[serialPort.BytesToRead];//创建接收数据数组
                        serialPort.Read(receivedData, 0, receivedData.Length);//读取数据
                        var content = string.Empty;
                        //显示形式
                        switch (showText)
                        {
                            case "16进制(HEX)":
                                for (int i = 0; i < receivedData.Length; i++)
                                {
                                    //ToString("X2") 为C#中的字符串格式控制符
                                    //X为     十六进制
                                    //2为 每次都是两位数
                                    content += (receivedData[i].ToString("X2") + " ");
                                }
                                break;
                            case "字符显示(ASCII)":
                                content = Encoding.GetEncoding("GB2312").GetString(receivedData);//防止乱码
                                break;
                        }
                        //接收文本框
                        this.txt_Received.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ffff")}:{content} \r\n");
                        serialPort.DiscardInBuffer();//丢弃缓存区数据
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error");
                    }
                }
                else
                {
                    MessageBox.Show("请打开串口", "Error");
                }
            }));
        }
View Code

11、完整代码

using System;
using System.Collections.Generic;
using System.Data;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace 虚拟串口通信
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        #region 初始话属性
        /// <summary>
        /// 实例化串口资源类
        /// </summary>
        private readonly System.IO.Ports.SerialPort serialPort = new System.IO.Ports.SerialPort();
        /// <summary>
        /// 波特率数值范围
        /// </summary>
        private readonly List<string> baudList = new List<string>() {
           "600","1200", "2400", "4800", "9600","14400", "19200", "28800","38400", "43000", "57600",
           "76800","115200","128000","230400","256000","460800","921600","1382400","自定义"
        };
        /// <summary>
        /// 停止位
        /// </summary>
        private readonly List<string> stopList = new List<string> { "1", "1.5", "2" };
        /// <summary>
        /// 数据位
        /// </summary>
        private readonly List<string> dataList = new List<string> { "5", "6", "7", "8" };
        /// <summary>
        /// 校验位
        /// </summary>
        private readonly List<string> checkList = new List<string>() { "NONE", "ODD", "EVEN", "MARK", "SPACE" };
        /// <summary>
        /// 数据显示
        /// </summary>
        private readonly List<string> showList = new List<string>() { "16进制(HEX)", "字符显示(ASCII)" };
        #endregion

        #region 界面加载
        /// <summary>
        /// 界面加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            //串口选择
            InitPorts();
            //波特率
            InitBaud();
            //停止位
            InitStop();
            //数据位
            InitData();
            //校验位
            InitCheck();
            //初始化数据显示
            InitDataShow();
            //实例化串口控件
            InitSerialPort();
        }
        #endregion

        #region 初始化
        /// <summary>
        /// 初始化串口控件
        /// </summary>
        public void InitSerialPort()
        {
            serialPort.DataReceived += Sp1_DataReceived;//指示已通过由 System.IO.Ports.SerialPort 对象表示的端口接收了数据
            serialPort.DtrEnable = true;//获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号。
            serialPort.RtsEnable = true;//获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号
            serialPort.ReadTimeout = 1000;//设置数据读取超时为1s
            serialPort.Close();
        }
        /// <summary>
        /// 扫描可用串口,初始化串口选择
        /// </summary>
        public void InitPorts()
        {
            this.cb_SelectComPort.DropDownStyle = ComboBoxStyle.DropDownList;//禁用输入功能
            this.cb_SelectComPort.Items.Clear();//清除原有串口
            var comPostList = System.IO.Ports.SerialPort.GetPortNames().ToList();//读取串口
            if (comPostList != null && comPostList.Any())
            {
                comPostList = comPostList.OrderBy(x => x).ToList();
                foreach (var item in comPostList)
                {
                    this.cb_SelectComPort.Items.Add(item);
                }
                this.cb_SelectComPort.Text = comPostList.FirstOrDefault();//默认选择第一个串口
                this.cb_SelectComPort.Enabled = true;//打开选择框
            }
            else
            {
                MessageBox.Show("本机未找到串口!!!", "Error");
            }
        }
        /// <summary>
        /// 初始化校验位
        /// </summary>
        public void InitCheck()
        {
            this.cb_CheckSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in checkList)
            {
                this.cb_CheckSelect.Items.Add(item);
            }
            this.cb_CheckSelect.SelectedItem = "NONE";
        }
        /// <summary>
        /// 初始化数据位
        /// </summary>
        public void InitData()
        {
            this.cb_DataSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in dataList)
            {
                this.cb_DataSelect.Items.Add(item);
            }
            this.cb_DataSelect.SelectedItem = "8";
        }
        /// <summary>
        /// 初始化停止位
        /// </summary>
        public void InitStop()
        {
            this.cb_StopSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            foreach (var item in stopList)
            {
                this.cb_StopSelect.Items.Add(item);
            }
            this.cb_StopSelect.SelectedItem = "1";
        }
        /// <summary>
        /// 初始化波特率
        /// </summary>
        public void InitBaud()
        {
            this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDownList;//不可手动输入
            foreach (var item in baudList)
            {
                this.cb_baudSelect.Items.Add(item);
            }
            this.cb_baudSelect.SelectedItem = "9600";
        }
        /// <summary>
        /// 初始化数据显示
        /// </summary>
        public void InitDataShow()
        {
            this.cb_DataShow.DropDownStyle = ComboBoxStyle.DropDownList;//不可手动输入
            foreach (var item in showList)
            {
                this.cb_DataShow.Items.Add(item);
            }
            this.cb_DataShow.SelectedItem = "字符显示(ASCII)";
        }
        #endregion

        #region 设置串口
        /// <summary>
        /// 设置串口信息
        /// </summary>
        private void SetSerialPort()
        {
            string strBuadRate = this.cb_baudSelect.Text.Trim();
            string strDataRate = this.cb_DataSelect.Text.Trim();
            string strCheckRate = this.cb_CheckSelect.Text.Trim();
            string strPortRate = this.cb_SelectComPort.Text.Trim();
            string strStopRate = this.cb_StopSelect.Text.Trim();
            int IBaudBits = Convert.ToInt32(strBuadRate);
            int IDataBits = Convert.ToInt32(strDataRate);
            serialPort.PortName = strPortRate;//设置串口号
            serialPort.BaudRate = IBaudBits;//设置波特率
            serialPort.DataBits = IDataBits;//设置数据位
            serialPort.Encoding = Encoding.UTF8;
            //设置校验位
            switch (strCheckRate)
            {
                case "NONE":
                    serialPort.Parity = Parity.None;
                    break;
                case "ODD":
                    serialPort.Parity = Parity.Odd;
                    break;
                case "EVEN":
                    serialPort.Parity = Parity.Even;
                    break;
                case "MARK":
                    serialPort.Parity = Parity.Mark;
                    break;
                case "SPACE":
                    serialPort.Parity = Parity.Space;
                    break;
                default:
                    serialPort.Parity = Parity.None;
                    break;
            }
            //设置停止位
            switch (strStopRate)
            {
                case "1":
                    serialPort.StopBits = StopBits.One;
                    break;
                case "1.5":
                    serialPort.StopBits = StopBits.OnePointFive;
                    break;
                case "2":
                    serialPort.StopBits = StopBits.Two;
                    break;
                default:
                    serialPort.StopBits = StopBits.One;
                    break;
            }
            serialPort.ReadTimeout = 5000;//读取超时时间5s
        }
        #endregion

        #region 波特率选择
        /// <summary>
        /// 波特率选择,自定义时允许输入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb_baudSelect_SelectedValueChanged(object sender, EventArgs e)
        {
            if (this.cb_baudSelect.SelectedItem?.ToString() == "自定义")
            {
                this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDown;
            }
            else
            {
                this.cb_baudSelect.DropDownStyle = ComboBoxStyle.DropDownList;
            }
        }
        #endregion

        #region 检测串口
        /// <summary>
        /// 检测串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_CheckPort_Click(object sender, EventArgs e)
        {
            this.cb_SelectComPort.Items.Clear();//清除原有串口选择数据
            var comPostList = System.IO.Ports.SerialPort.GetPortNames().ToList();//读取串口
            if (comPostList != null && comPostList.Any())
            {
                comPostList = comPostList.OrderBy(x => x).ToList();
                foreach (var item in comPostList)
                {
                    this.cb_SelectComPort.Items.Add(item);
                }
                this.cb_SelectComPort.Text = comPostList.FirstOrDefault();//默认选择第一个串口
            }
            else
            {
                MessageBox.Show("本机未找到串口!!!", "Error");
            }
        }
        #endregion

        #region 打开\关闭串口
        /// <summary>
        /// 打开\关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_OpenOrrEndCom_Click(object sender, EventArgs e)
        {
            //串口是否打开
            if (!serialPort.IsOpen)
            {
                try
                {
                    this.btn_OpenOrrEndCom.Text = "关闭串口";
                    //如果打开状态,则先关闭一下
                    if (serialPort.IsOpen)
                    {
                        serialPort.Close();
                    }
                    //设置串口
                    SetSerialPort();
                    //打开串口后不允许更改
                    this.cb_baudSelect.Enabled = false;
                    this.cb_CheckSelect.Enabled = false;
                    this.cb_SelectComPort.Enabled = false;
                    this.cb_StopSelect.Enabled = false;
                    this.cb_DataSelect.Enabled = false;
                    //打开
                    serialPort.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("打开串口失败:" + ex.Message);
                    throw;
                }
            }
            else
            {
                this.cb_baudSelect.Enabled = true;
                this.cb_CheckSelect.Enabled = true;
                this.cb_SelectComPort.Enabled = true;
                this.cb_StopSelect.Enabled = true;
                this.cb_DataSelect.Enabled = true;
                this.btn_OpenOrrEndCom.Text = "打开串口";
                serialPort.Close();//关闭
            }
        }
        #endregion

        #region 发送与接收数据
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Send_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                try
                {
                    byte[] sendData = null;
                    string send = this.txt_Send.Text.Trim();
                    var showText = this.cb_DataShow.Text;
                    //按照指定编码将string编程字节数组
                    byte[] b = Encoding.GetEncoding("GBK").GetBytes(send);
                    if (showText == "16进制(HEX)")
                    {
                        string result = string.Empty;
                        //逐字节变为16进制字符
                        for (int i = 0; i < b.Length; i++)
                        {
                            result += Convert.ToString(b[i], 16).ToUpper() + " ";
                        }
                        sendData = Encoding.GetEncoding("GBK").GetBytes(result);
                    }
                    else
                    {
                        sendData = b;
                    }
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {

                    MessageBox.Show("发送失败:" + ex.Message, "Error");
                }
            }
            else
            {
                MessageBox.Show("请先打开串口", "Error");
            }
        }
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //异步委托一个线程,不然接收数据时会出现数据线程错误
            this.Invoke((EventHandler)(delegate
            {
                var showText = this.cb_DataShow.Text;
                if (serialPort.IsOpen)
                {
                    try
                    {
                        byte[] receivedData = new byte[serialPort.BytesToRead];//创建接收数据数组
                        serialPort.Read(receivedData, 0, receivedData.Length);//读取数据
                        var content = string.Empty;
                        //显示形式
                        switch (showText)
                        {
                            case "16进制(HEX)":
                                for (int i = 0; i < receivedData.Length; i++)
                                {
                                    //ToString("X2") 为C#中的字符串格式控制符
                                    //X为     十六进制
                                    //2为 每次都是两位数
                                    content += (receivedData[i].ToString("X2") + " ");
                                }
                                break;
                            case "字符显示(ASCII)":
                                content = Encoding.GetEncoding("GB2312").GetString(receivedData);//防止乱码
                                break;
                        }
                        //接收文本框
                        this.txt_Received.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss:ffff")}:{content} \r\n");
                        serialPort.DiscardInBuffer();//丢弃缓存区数据
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "Error");
                    }
                }
                else
                {
                    MessageBox.Show("请打开串口", "Error");
                }
            }));
        }
        #endregion
    }
}
View Code

12、测试结果

 

 

就以上测试结果来看需要的效果以达成。

13、Demo下载

 Demo下载地址:C# WinForm虚拟串口通信