Winform串口编程---接收数据demo(VSPD虚拟串口)
参考地址:https://blog.csdn.net/memgxingfeixiang/article/details/52513970
https://blog.csdn.net/kevin_iot/article/details/53926599
一、需求概述
应用场景:winform中能接收到串口发送的数据。
所需软件: Configure Virtual Serial Port Driver(虚拟串口模拟软件)、串口调试助手。
二、效果展示(很简陋,捂脸中......)
说明:cmbPort是电脑上所有串口的列表,txtReciveData是每次该串口接收的数据,btnOpenOrClose按钮是控制打开/关闭串口。
三、具体实现:
(1)先在Load事件里将comPort控件绑定电脑串口列表,代码如下:
1 #region 初始化电脑上的串口列表 2 foreach (string sPort in SerialPort.GetPortNames()) 3 { 4 cmbPort.Items.Add(sPort); 5 } 6 7 //串口设置默认选项 8 if (cmbPort.Items.Count>0) 9 { 10 cmbPort.SelectedIndex = 0; 11 } 12 #endregion
(2)编写btnOpenOrClose点击事件
1 /// <summary> 2 /// 打开/关闭串口 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void btnOpenOrClose_Click(object sender, EventArgs e) 7 { 8 try 9 { 10 if (btnOpenOrClose.Text == "打开串口") 11 { 12 btnOpenOrClose.Text = "关闭串口"; 13 //设置串口的基本属性 14 serialPort.PortName = cmbPort.SelectedItem.ToString(); 15 serialPort.BaudRate = 9600; 16 serialPort.Parity = Parity.None; 17 serialPort.DataBits = 8; 18 serialPort.StopBits = StopBits.One; 19 serialPort.Open(); 20 } 21 else 22 { 23 btnOpenOrClose.Text = "打开串口"; 24 serialPort.Close(); 25 } 26 } 27 catch (Exception ex) 28 { 29 MessageBox.Show(ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 30 return; 31 } 32 }
(3)编写接收串口数据方法
1 void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e) 2 { 3 try 4 { 5 Byte[] InputBuf = new Byte[128]; 6 serialPort.Read(InputBuf, 0, serialPort.BytesToRead); 7 8 ASCIIEncoding encoding = new ASCIIEncoding(); 9 data = encoding.GetString(InputBuf); 10 new Thread(SetReceiveData).Start(); 11 //直接调用会报错-------从不是创建控件”txtContent”的线程访问它 12 //SetReceiveData(); 13 } 14 catch (Exception ex) 15 { 16 MessageBox.Show(ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 17 return; 18 } 19 }
接收数据成功,调用下面的方法,将发送的数据显示到文本框中。
1 /// <summary> 2 /// (将接收的数据显示到文本框中)不懂这一块的实现逻辑,需要加深理解线程的相关概念 3 /// </summary> 4 public void SetReceiveData() 5 { 6 lock (this) 7 8 Invoke(new MethodInvoker(delegate () 9 10 { 11 12 this.txtReciveData.Text = data; 13 14 })); 15 16 }
在load事件中将订阅该事件
//为串口加上数据接收事件 serialPort.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived);
四:模拟串口发送数据
(1)打开vspd软件,虚拟出两个COM1和COM2两个串口
(2)打开串口调试助手,一个是COM1,另外一个是COM2,将两个串口的波特率设置为一样。
测试一下,两个串口是否能正常通讯。
(3)关掉其中的一个串口调试助手,留下COM2的串口调试助手,我们在程序中用COM1口接收数据。(winform中要先点击“打开串口”按钮)
五、完整代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 using System.IO.Ports; 11 using System.Threading; 12 13 namespace ComDataTest 14 { 15 public partial class ComData : Form 16 { 17 private SerialPort serialPort=new SerialPort(); 18 string data = string.Empty; 19 public ComData() 20 { 21 InitializeComponent(); 22 } 23 24 private void ComData_Load(object sender, EventArgs e) 25 { 26 #region 初始化电脑上的串口列表 27 foreach (string sPort in SerialPort.GetPortNames()) 28 { 29 cmbPort.Items.Add(sPort); 30 } 31 32 //串口设置默认选项 33 if (cmbPort.Items.Count>0) 34 { 35 cmbPort.SelectedIndex = 0; 36 } 37 #endregion 38 39 //为串口加上数据接收事件 40 serialPort.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived); 41 } 42 43 /// <summary> 44 /// 打开/关闭串口 45 /// </summary> 46 /// <param name="sender"></param> 47 /// <param name="e"></param> 48 private void btnOpenOrClose_Click(object sender, EventArgs e) 49 { 50 try 51 { 52 if (btnOpenOrClose.Text == "打开串口") 53 { 54 btnOpenOrClose.Text = "关闭串口"; 55 //设置串口的基本属性 56 serialPort.PortName = cmbPort.SelectedItem.ToString(); 57 serialPort.BaudRate = 9600; 58 serialPort.Parity = Parity.None; 59 serialPort.DataBits = 8; 60 serialPort.StopBits = StopBits.One; 61 serialPort.Open(); 62 } 63 else 64 { 65 btnOpenOrClose.Text = "打开串口"; 66 serialPort.Close(); 67 } 68 } 69 catch (Exception ex) 70 { 71 MessageBox.Show(ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 72 return; 73 } 74 } 75 76 /// <summary> 77 /// (将接收的数据显示到文本框中)不懂这一块的实现逻辑,需要加深理解线程的相关概念 78 /// </summary> 79 public void SetReceiveData() 80 { 81 lock (this) 82 83 Invoke(new MethodInvoker(delegate () 84 85 { 86 87 this.txtReciveData.Text = data; 88 89 })); 90 91 } 92 93 void Comm_DataReceived(object sender, SerialDataReceivedEventArgs e) 94 { 95 try 96 { 97 Byte[] InputBuf = new Byte[128]; 98 serialPort.Read(InputBuf, 0, serialPort.BytesToRead); 99 100 ASCIIEncoding encoding = new ASCIIEncoding(); 101 data = encoding.GetString(InputBuf); 102 new Thread(SetReceiveData).Start(); 103 //直接调用会报错-------从不是创建控件”txtContent”的线程访问它 104 //SetReceiveData(); 105 } 106 catch (Exception ex) 107 { 108 MessageBox.Show(ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 109 return; 110 } 111 } 112 } 113 }
六、写在后面的话:
初次接触串口编程,作为码农多年,确实有些汗颜。从最初下载vspd和串口调试软件,根本不知如何用,到慢慢的了解一些,会简单的一些操作,着实也费了一点时间。目前对于串口编程,还是有一些云里雾里,似乎缺少一根主线把他们串起来一般,还是需要再进行摸索和探究,继续加油~