現在大多數硬體裝置均採用串口技術與電腦相連,因此串口的應用程式開發越來越普遍。例如,在電腦沒有安裝網卡的情況下,將本機上的一些資訊資料轉送到另一台電腦上,那麼利用串口通訊就可以實現。運行本程式,在“發送資料”文字框中輸入要傳送的資料,單擊【發送】按鈕,將傳送的資料發送到所選擇的連接埠號碼中;單擊【接收】按鈕,傳遞的資料被接收到“接收資料”文字框中。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());
這種奇怪的方法可以解決問題,後來想想應該是串口的工作方式決定的也有可能,期待其他的解決方