現在大多數硬件設備均採用串口技術與計算機相連,因此串口的應用程序開發越來越普遍。例如,在計算機沒有安裝網卡的情況下,將本機上的一些信息數據 傳輸到另一臺計算機上,那麼利用串口通信就可以實現。運行本程序,在“發送數據”文本框中輸入要傳送的數據,單擊【發送】按鈕,將傳送的數據發送到所選擇 的端口號中;單擊【接收】按鈕,傳遞的數據被接收到“接收數據”文本框中。如圖13.1所示。
技術要點
在.NET Framework 2.0中提供了SerialPort類,該類主要實現串口數據通信等。下面主要介紹該類的主要屬性(表13.1)和方法(表13.2)。
表13.1 SerialPort類的常用屬性
名 稱 |
說 明 |
BaseStream |
獲取 SerialPort 對象的基礎 Stream 對象 |
BaudRate |
獲取或設置串行波特率 |
BreakState |
獲取或設置中斷信號狀態 |
BytesToRead |
獲取接收緩衝區中數據的字節數 |
BytesToWrite |
獲取發送緩衝區中數據的字節數 |
CDHolding |
獲取端口的載波檢測行的狀態 |
CtsHolding |
獲取“可以發送”行的狀態 |
DataBits |
獲取或設置每個字節的標準數據位長度 |
DiscardNull |
獲取或設置一個值,該值指示 Null 字節在端口和接收緩衝區之間傳輸時是否被忽略 |
DsrHolding |
獲取數據設置就緒 (DSR) 信號的狀態 |
DtrEnable |
獲取或設置一個值,該值在串行通信過程中啓用數據終端就緒 (DTR) 信號 |
Encoding |
獲取或設置傳輸前後文本轉換的字節編碼 |
Handshake |
獲取或設置串行端口數據傳輸的握手協議 |
IsOpen |
獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態 |
NewLine |
獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值 |
Parity |
獲取或設置奇偶校驗檢查協議 |
續表
名 稱 |
說 明 |
ParityReplace |
獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節 |
PortName |
獲取或設置通信端口,包括但不限於所有可用的 COM 端口 |
ReadBufferSize |
獲取或設置 SerialPort 輸入緩衝區的大小 |
ReadTimeout |
獲取或設置讀取操作未完成時發生超時之前的毫秒數 |
ReceivedBytesThreshold |
獲取或設置 DataReceived 事件發生前內部輸入緩衝區中的字節數 |
RtsEnable |
獲取或設置一個值,該值指示在串行通信中是否啓用請求發送 (RTS) 信號 |
StopBits |
獲取或設置每個字節的標準停止位數 |
WriteBufferSize |
獲取或設置串行端口輸出緩衝區的大小 |
WriteTimeout |
獲取或設置寫入操作未完成時發生超時之前的毫秒數 |
表13.2 SerialPort類的常用方法
方 法 名 稱 |
說 明 |
Close |
關閉端口連接,將 IsOpen 屬性設置爲False,並釋放內部 Stream 對象 |
Open |
打開一個新的串行端口連接 |
Read |
從 SerialPort 輸入緩衝區中讀取 |
ReadByte |
從 SerialPort 輸入緩衝區中同步讀取一個字節 |
ReadChar |
從 SerialPort 輸入緩衝區中同步讀取一個字符 |
ReadLine |
一直讀取到輸入緩衝區中的 NewLine 值 |
ReadTo |
一直讀取到輸入緩衝區中指定 value 的字符串 |
Write |
已重載。將數據寫入串行端口輸出緩衝區 |
WriteLine |
將指定的字符串和 NewLine 值寫入輸出緩衝區 |
注意:用跳線使串口的第2、3針連接,可以在本地計算機上實現串口通信,所以,通過串口的第2、3針的連接可以對程序進行檢測。串口截面圖如圖13.2所示。
圖13.2 串口截面圖
實現過程
(1)新建一個項目,命名爲Ex13_01,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,分別用於執行發送數據和接受數據,添加兩個TextBox控件,用於輸入發送數據和顯示接收數據。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.Open();
byte[] data = Encoding.Unicode.GetBytes(textBox1.Text);
string str = Convert.ToBase64String(data);
serialPort1.WriteLine(str);
MessageBox.Show("數據發送成功!","系統提示");
}
private void button2_Click(object sender, EventArgs e)
{
byte[] data = Convert.FromBase64String(serialPort1.ReadLine());
textBox2.Text = Encoding.Unicode.GetString(data);
serialPort1.Close();
MessageBox.Show("數據接收成功!","系統提示");
}
舉一反三
根據本實例,讀者可以實現以下功能。
遠程監控對方計算機屏幕。
下位機控制程序。
實例419 通過串口關閉對方計算機
實例說明
在網絡應用程序中,主要通過網卡實現數據的傳輸,因此可以利用套接字技術實現遠程關閉計算機。如果計算機中沒有安裝網卡,該如何實現遠程關閉計算機呢?本例實現了利用串口關閉對方計算機,程序運行結果如圖13.3所示。
技術要點
本實例使用SerialPort類的屬性和方法,請參見實例“通過串口發送數據”。下面主要介紹SerialPort類的DataReceived 事件,DataReceived 事件爲本實例的主要使用技術。DataReceived事件表示將處理 SerialPort 對象的數據接收事件的方法。串行接收事件可以由 SerialData 枚舉中的任何項引起,是否引發此事件由操作系統決定,所以不一定會報告所有奇偶校驗錯誤。
注意:本實例從開發到測試,都是由本地計算機完成的,用戶只需要使用跳線將串口的第2、3針連接,可以在本地計算機上實現串口通信。跳線連接請參見圖13.2。
實現過程
(1)新建一個項目,命名爲Ex13_02,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,分別用於打開通信串口和關閉對方計算機。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
//打開串口
serialPort1.PortName = "COM1";
serialPort1.Open();
button1.Enabled = false;
button2.Enabled = true;
} //數據接收事件,等待接收關機命令
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] data = Convert.FromBase64String(serialPort1.ReadLine());
string str = Encoding.Unicode.GetString(data);
serialPort1.Close();
if (str == "關機")
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("shutdown /s");
p.StandardInput.WriteLine("exit");
}
} //發送關機命令
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "關閉計算機")
{
//發送關機命令數據
byte[] data = Encoding.Unicode.GetBytes("關機");
string str = Convert.ToBase64String(data);
serialPort1.WriteLine(str);
button2.Text = "取消關機";
}
else
{
button2.Text = "關閉計算機";
button1.Enabled = true;
button2.Enabled = false;
//取消關機
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("shutdown /a");
p.StandardInput.WriteLine("exit");
}
}
在我的測試軟件中發現一個問題,就是當發送數據小於或等於8位時,一切正常,如果大於8爲字節,則在datareceived事件中接收到的數據會分成兩段,第一段爲8位,第二段爲剩下的字節,很奇怪,在msdn中講到不能保證每次發送的數據都能正確接收到,需要參照BytesToRead屬性來確定要讀取的數據量,所以我想出來的解決辦法爲:
int DataLength=serialPort.BytesToRead;
int i=0;
StringBuilder sb=new StringBuilder();
while(i<DataLength)
{
byte[] ds=new byte[1024];
int len=serialPort.Read(ds,0,1024);
sb.Append(Encoding.Ascii.GetString(ds,0,len));
i+=len;
}
Console.Write(sb,ToString());
這種奇怪的方法可以解決問題,後來想想應該是串口的工作方式決定的也有可能,期待其他的解決方式。