上次說到了協議的大致結構,這次我們來說說怎么去實現制動連接串口(當你把設備連上來之后,怎么去讓軟件自動去識別是否為目標設備,當然這需要上位機與下位機共同完成,這里我們只討論上位機部分)
先上協議:
幀頭(3)+設備號(1)+指令類型(2)+數據長度(2)+載荷+CRC(2)
需要在下位機上實現的部分:
接收到一幀數據(幀頭為53 5A 59,設備號01,類型為02,載荷無)53 59 A2 01 02 00 00 00 CRC后,會返回(幀頭為53 5A 59,設備號01,類型為02,載荷為"6F 6B")53 5A 59 01 02 00 02 00 6F 6B CRC則表示指令接收成功。
下面說我的思路,在軟件界面打開后,開一個自動連接線程處理連接部分。具體步驟是:
獲取計算機所有串口。
嘗試發送指定數據到每個可用串口。
嘗試從串口接收數據並檢查是否為約定數據,若是則綁定該端口,完成連接。不是則換到下一個。循環。
好了,讓我們簡單點,下面直接上代碼:
bool IsConnected = false; private void AutoConcted() { while (true)//循環 { while (!IsConnected)//未連接 { string[] strPorNnames = SerialPort.GetPortNames();//獲取所有可用串口名 foreach (string portName in strPorNnames)//遍歷串口 { try { SPort.PortName = portName; SPort.Open(); SPort.DiscardOutBuffer(); byte[] bytSend = new byte[] { 0x53, 0x59, 0xA2, 0x01, 0x02, 0x00, 0x00, 0x00, CRC };//自行去CRC去 SPort.Write(bytSend, 0, bytSend.Length); Thread.Sleep(100);//確保數據發送及解析時間 int n = SPort.BytesToRead; byte[] bytRec = new byte[n]; SPort.Read(bytRec, 0, n); if (IsHertJump(bytRec))//判斷返回是否為指定數據 { IsConnected = true; break;//是則跳出循環 } else { SPort.Close(); } } catch (Exception) { SPort.Close(); } } Thread.Sleep(400); } } }
是的,自動連接應該可以實現了,然而又有了新問題,這種自動連接貌似只能連一次,中途拔掉一下就不行了,因為連接上之后進程就自己銷毀了。而且拔掉之后(串口斷開)軟件並不會有任何的狀態提示,之后你所有的數據都會往一個不知道的地方去了。所以,我們還要加一個檢測斷開的機制。由於兩者不會同時需要,所以可以寫到一個線程里去,沒連上就自動去連,連上了就檢測是否斷開。
修改后的代碼:(完善后的自動連接線程)
private void AutoConcted() { while (true) { while (!IsConnected) { string[] strPorNnames = SerialPort.GetPortNames(); foreach (string portName in strPorNnames) { try { SPort.PortName = portName; SPort.Open(); SPort.DiscardOutBuffer(); byte[] bytSend = new byte[] { 0x53, 0x59, 0xA2, 0x01, 0x02, 0x00, 0x00, 0x00, CRC };//自行去CRC去 SPort.Write(bytSend, 0, bytSend.Length); Thread.Sleep(100); int n = SPort.BytesToRead; byte[] bytRec = new byte[n]; SPort.Read(bytRec, 0, n); if (IsHertJump(bytRec)) { IsConnected = true; break; } else { SPort.Close(); } } catch (Exception) { SPort.Close(); } } Thread.Sleep(400); } while (IsConnected) { if (!SPort.IsOpen)//檢查是否斷開 { SPort.Close(); IsConnected = false; } Thread.Sleep(1000); } } }