這節介紹實作的是利用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))進行連接配接。
我們現階段主要實作的從序列槽中擷取資料,寫資料暫時不需要,是以我們可以在裡面提取我們需要的部分。
在文檔的左側,我們可以選擇其方法和事件來選擇我們所需要的執行個體。
選取事件中的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的使用,有興趣的可以先體驗實作一下,然後我們看一下我們程式裡面使用的版本。
看一下界面:
界面實作,兩個 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;
}
SerialPort類到此就介紹完成了,完成到這裡,你的項目已經具備了連接配接序列槽、接收資料的功能了(更新UI的代碼在更新Ui章節貼出)。
自備序列槽助手這個就不用說了,除此之外建議大家安裝一個虛拟序列槽工具,在大家沒有連接配接硬體的情況下,通過序列槽助手發送資料,也能進行測試。
我用的是Configure Virtual Serial Port Driver,添加端口就能用,一個發一個收,還挺好用的。
下一節介紹Chart圖表的應用。