頁面修改爲這樣子html
如今看串口發送數據 數組
點擊點亮 發送0xaa 0x55 0x01 緩存
我電腦上安裝了虛擬串口軟件,虛擬出來了COM1和COM2,而後COM1發送的數據會發給COM2 COM2發送的數據會發給COM1函數
你們若是有兩個串口模塊也能夠測試
https://jingyan.baidu.com/article/e3c78d648965303c4c85f535.html優化
那個按鈕的程序這樣寫spa
測試一下線程
如今看串口接收數據3d
說一下哈,這個是上位機的串口中斷函數,就是隻要接收到數據就會進入這個中斷code
如今咱讀出來接收的數據,而後顯示在
讀取數據給了好幾個方法
咱就說1個,哈哈哈,其實本身一選擇方法的時候就有中文註釋......
你們注沒注意
如今調用一個函數讀出來,而後顯示出來
ReadExisting() 這個方法就會返回緩衝區裏面的全部字節,注意返回的是字符串形式的
調用這個方法就是 serialPort1.ReadExisting(); serialPort1就是咱的
由於咱就是要裏面的數據因此
string str = serialPort1.ReadExisting();//讀出來當前緩存裏面的全部數據
Invoke((new Action(() =>
{
這裏面放要操做的主線程的控件的方法
})));
其實這個方法主要是方便解決一個問題,稍候再說,咱先測試一下哈
說明能夠了,如今呢,咱去掉
你們能夠點開那個 如何跨線程調用 Windows 窗體控件
你們能夠看這個 http://www.javashuo.com/article/p-bcpnbylk-r.html (最好別看,看了就會感受麻煩)
4.0以後引進了這種方法
對於初學者知道這個就能夠了,像C#,C++,JAVA等等這種高級語言哈,由於能夠作界面了,,高級語言規定,操做頁面不能在子線程中進行
哪些是子線程呢!..像上面那個串口中斷函數,還有本身建立的任務Thread,,,等等吧
好如今,咱接收16進制,
接收到
0xaa 0x55 0x01
0xaa 0x55 0x00
好,上菜
//串口接收到數據就會進入 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { int len = serialPort1.BytesToRead;//獲取能夠讀取的字節數 if (len > 0) { byte[] recvBytes = new byte[len];//建立接收的數組 serialPort1.Read(recvBytes, 0, len);//接收數據 if (recvBytes[0] == 0xaa && recvBytes[1] == 0x55)//判斷數據 { if (recvBytes[2] == 0x01)// { Invoke((new Action(() => { button3.Text = "熄滅"; label5.Text = "點亮"; }))); } else if (recvBytes[2] == 0x00) { Invoke((new Action(() => { button3.Text = "點亮"; label5.Text = "熄滅"; }))); } } } //string str = serialPort1.ReadExisting();//讀出來當前緩存裏面的全部數據 //Invoke((new Action(() => //{ // //顯示在文本框裏面 // textBox1.AppendText(str); //}))); }
測試
雖然能夠了,可是這樣寫不保險...
緣由是那個中斷是不定長的數據就進去(受到電腦總體運行狀態的影響),因此呢咱優化下
//串口接收到數據就會進入 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { int len = serialPort1.BytesToRead;//獲取能夠讀取的字節數 if (len > 0) { byte[] recvBytes = new byte[len];//建立接收的數組 serialPort1.Read(recvBytes, 0, len);//接收數據 for (int i = 0; i < len; i++)//拷貝數據到UsartReadBuff { UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接着填入數據 } UsartReadCnt = UsartReadCnt + len;//記錄上次的數據個數 if (UsartReadCnt >= 3)//接收到能夠處理的數據個數 { UsartReadCnt = 0; if (UsartReadBuff[0] == 0xaa && UsartReadBuff[1] == 0x55)//判斷數據 { if (UsartReadBuff[2] == 0x01)// { Invoke((new Action(() => { button3.Text = "熄滅"; label5.Text = "點亮"; }))); } else if (UsartReadBuff[2] == 0x00) { Invoke((new Action(() => { button3.Text = "點亮"; label5.Text = "熄滅"; }))); } } } } //string str = serialPort1.ReadExisting();//讀出來當前緩存裏面的全部數據 //Invoke((new Action(() => //{ // //顯示在文本框裏面 // textBox1.AppendText(str); //}))); }
本身測試哈
如今說一下
若是接收的是字符串,想顯示出來
若是發過來了16進制 注意哈,發過來的是16進制 假設 00 就是數字0 由於那個文本框顯示的時候是顯示的字符串
因此須要轉成 "00" 發過來0F 須要顯示字符串形式的 "0F"
給你們準備好了
/// <字節數組轉16進制字符串> /// <param name="bytes"></param> /// <returns> String 16進制顯示形式</returns> public static string byteToHexStr(byte[] bytes) { string returnStr = ""; try { if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); returnStr += " ";//兩個16進制用空格隔開,方便看數據 } } return returnStr; } catch (Exception) { return returnStr; } }
//串口接收到數據就會進入 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { int len = serialPort1.BytesToRead;//獲取能夠讀取的字節數 if (len > 0) { byte[] recvBytes = new byte[len];//建立接收的數組 serialPort1.Read(recvBytes, 0, len);//接收數據 Invoke((new Action(() =>//顯示字符串 { textBox1.AppendText("字符串:"+Encoding.Default.GetString(recvBytes)); //顯示在文本框裏面 }))); Invoke((new Action(() =>//顯示16進制 { textBox1.AppendText("\r\n16進制:" + byteToHexStr(recvBytes) + "\r\n"); //顯示在文本框裏面 }))); for (int i = 0; i < len; i++)//拷貝數據到UsartReadBuff { UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接着填入數據 } UsartReadCnt = UsartReadCnt + len;//記錄上次的數據個數 if (UsartReadCnt >= 3)//接收到能夠處理的數據個數 { UsartReadCnt = 0; if (UsartReadBuff[0] == 0xaa && UsartReadBuff[1] == 0x55)//判斷數據 { if (UsartReadBuff[2] == 0x01)// { Invoke((new Action(() => { button3.Text = "熄滅"; label5.Text = "點亮"; }))); } else if (UsartReadBuff[2] == 0x00) { Invoke((new Action(() => { button3.Text = "點亮"; label5.Text = "熄滅"; }))); } } } } }
如今看發送
發送就只作字符串發送哈,,,16進制發送後期補上,,你們先吸取吸取如今的....
執行文件
我把16進制發送用到的函數放在這裏,後期再回來加上
/// <字符串轉16進制格式,不夠自動前面補零> /// /// </summary> /// <param name="hexString"></param> /// <returns></returns> private static byte[] strToToHexByte(String hexString) { int i; bool Flag = false; hexString = hexString.Replace(" ", "");//清除空格 if ((hexString.Length % 2) != 0) { Flag = true; } if (Flag == true) { byte[] returnBytes = new byte[(hexString.Length + 1) / 2]; try { for (i = 0; i < (hexString.Length - 1) / 2; i++) { returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16); } catch { for (i = 0; i < returnBytes.Length; i++) { returnBytes[i] = 0; } MessageBox.Show("超過16進制範圍A-F,已初始化爲0", "提示"); } return returnBytes; } else { byte[] returnBytes = new byte[(hexString.Length) / 2]; try { for (i = 0; i < returnBytes.Length; i++) { returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); } } catch { for (i = 0; i < returnBytes.Length; i++) { returnBytes[i] = 0; } MessageBox.Show("超過16進制範圍A-F,已初始化爲0", "提示"); } return returnBytes; } }
對了,其實上位機串口是有空閒時間中斷的(異常捕獲),只不過,我還沒細研究呢!!!