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和串列埠除錯軟體,根本不知如何用,到慢慢的瞭解一些,會簡單的一些操作,著實也費了一點時間。目前對於串列埠程式設計,還是有一些雲裡霧裡,似乎缺少一根主線把他們串起來一般,還是需要再進行摸索和探究,繼續加油~