https://www.cnblogs.com/yangfengwu/p/11087613.html
頁面修改成這樣子




現(xiàn)在看串口發(fā)送數(shù)據(jù)?
點擊點亮?發(fā)送0xaa 0x55 0x01 ? ?

我電腦上安裝了虛擬串口軟件,虛擬出來了COM1和COM2,然后COM1發(fā)送的數(shù)據(jù)會發(fā)給COM2 ?COM2發(fā)送的數(shù)據(jù)會發(fā)給COM1
大家如果有兩個串口模塊也可以


https://jingyan.baidu.com/article/e3c78d648965303c4c85f535.html
那個按鈕的程序這樣寫


?測試一下

現(xiàn)在看串口接收數(shù)據(jù)


說一下哈,這個是上位機的串口中斷函數(shù),就是只要接收到數(shù)據(jù)就會進入這個中斷
現(xiàn)在咱讀出來接收的數(shù)據(jù),然后顯示在

讀取數(shù)據(jù)給了好幾個方法
咱就說1個,哈哈哈,其實自己一選擇方法的時候就有中文注釋......

大家注沒注意

現(xiàn)在調(diào)用一個函數(shù)讀出來,然后顯示出來

ReadExisting() ? 這個方法就會返回緩沖區(qū)里面的所有字節(jié),注意返回的是字符串形式的
調(diào)用這個方法就是 ?serialPort1.ReadExisting(); ? ? ??serialPort1就是咱的

因為咱就是要里面的數(shù)據(jù)所以 ?
string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數(shù)據(jù)
Invoke((new Action(() =>
{
? ? 這里面放要操作的主線程的控件的方法
})));
其實這個方法主要是方便解決一個問題,稍候再說,咱先測試一下哈

?說明可以了,現(xiàn)在呢,咱去掉



?大家可以點開那個? 如何跨線程調(diào)用 Windows 窗體控件
大家可以看這個https://www.cnblogs.com/yangfengwu/p/5761841.html(最好別看,看了就會感覺麻煩)
4.0之后引進了這種方法

對于初學(xué)者知道這個就可以了,像C#,C++,JAVA等等這種高級語言哈,因為可以做界面了,,高級語言規(guī)定,操作頁面不能在子線程中進行
哪些是子線程呢!..像上面那個串口中斷函數(shù),還有自己創(chuàng)建的任務(wù)Thread,,,等等吧
好現(xiàn)在,咱接收16進制,
接收到
0xaa 0x55 0x01??

0xaa 0x55 0x00??

好,上菜

//串口接收到數(shù)據(jù)就會進入privatevoidserialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
? ? ? ? {
? ? ? ? ? ? intlen = serialPort1.BytesToRead;//獲取可以讀取的字節(jié)數(shù)if(len >0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? byte[] recvBytes =newbyte[len];//創(chuàng)建接收的數(shù)組serialPort1.Read(recvBytes,0, len);//接收數(shù)據(jù)if(recvBytes[0] ==0xaa&& recvBytes[1] ==0x55)//判斷數(shù)據(jù)? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if(recvBytes[2] ==0x01)//? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? elseif(recvBytes[2] ==0x00)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數(shù)據(jù)
? ? ? ? ? ? //Invoke((new Action(() =>
? ? ? ? ? ? //{
? ? ? ? ? ? ////顯示在文本框里面
? ? ? ? ? ? //? ? textBox1.AppendText(str);
? ? ? ? ? ? //})));}


測試


雖然可以了,但是這樣寫不保險...
原因是那個中斷是不定長的數(shù)據(jù)就進去(受到電腦整體運行狀態(tài)的影響),所以呢咱優(yōu)化下


//串口接收到數(shù)據(jù)就會進入privatevoidserialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
? ? ? ? {
? ? ? ? ? ? intlen = serialPort1.BytesToRead;//獲取可以讀取的字節(jié)數(shù)if(len >0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? byte[] recvBytes =newbyte[len];//創(chuàng)建接收的數(shù)組serialPort1.Read(recvBytes,0, len);//接收數(shù)據(jù)for(inti =0; i < len; i++)//拷貝數(shù)據(jù)到UsartReadBuff? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接著填入數(shù)據(jù)? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? UsartReadCnt = UsartReadCnt + len;//記錄上次的數(shù)據(jù)個數(shù)if(UsartReadCnt >=3)//接收到可以處理的數(shù)據(jù)個數(shù)? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? UsartReadCnt =0;
? ? ? ? ? ? ? ? ? ? if(UsartReadBuff[0] ==0xaa&& UsartReadBuff[1] ==0x55)//判斷數(shù)據(jù)? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? if(UsartReadBuff[2] ==0x01)//? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? elseif(UsartReadBuff[2] ==0x00)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? //string str = serialPort1.ReadExisting();//讀出來當前緩存里面的所有數(shù)據(jù)
? ? ? ? ? ? //Invoke((new Action(() =>
? ? ? ? ? ? //{
? ? ? ? ? ? ////顯示在文本框里面
? ? ? ? ? ? //? ? textBox1.AppendText(str);
? ? ? ? ? ? //})));}

自己測試哈
現(xiàn)在說一下

?如果接收的是字符串,想顯示出來


如果發(fā)過來了16進制? ?注意哈,發(fā)過來的是16進制? 假設(shè) 00? 就是數(shù)字0? ?因為那個文本框顯示的時候是顯示的字符串
所以需要轉(zhuǎn)成? "00"? ? 發(fā)過來0F? ?需要顯示字符串形式的? "0F"
給大家準備好了

///<字節(jié)數(shù)組轉(zhuǎn)16進制字符串>///<param name="bytes"></param>///<returns> String 16進制顯示形式</returns>publicstaticstringbyteToHexStr(byte[] bytes)
? ? ? ? {
? ? ? ? ? ? stringreturnStr ="";
? ? ? ? ? ? try? ? ? ? ? ? {
? ? ? ? ? ? ? ? if(bytes !=null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? for(inti =0; i < bytes.Length; i++)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? returnStr += bytes[i].ToString("X2");
? ? ? ? ? ? ? ? ? ? ? ? returnStr +="";//兩個16進制用空格隔開,方便看數(shù)據(jù)? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return returnStr;
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return returnStr;
? ? ? ? ? ? }
? ? ? ? }


//串口接收到數(shù)據(jù)就會進入privatevoidserialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
? ? ? ? {
? ? ? ? ? ? intlen = serialPort1.BytesToRead;//獲取可以讀取的字節(jié)數(shù)if(len >0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? byte[] recvBytes =newbyte[len];//創(chuàng)建接收的數(shù)組serialPort1.Read(recvBytes,0, len);//接收數(shù)據(jù)? ? ? ? ? ? ? ? Invoke((newAction(() =>//顯示字符串? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? textBox1.AppendText("字符串:"+Encoding.Default.GetString(recvBytes));//顯示在文本框里面? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? Invoke((newAction(() =>//顯示16進制? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? textBox1.AppendText("\r\n16進制:"+ byteToHexStr(recvBytes) +"\r\n");//顯示在文本框里面? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? for(inti =0; i < len; i++)//拷貝數(shù)據(jù)到UsartReadBuff? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? UsartReadBuff[i+ UsartReadCnt] = recvBytes[i];//從上次的地方接著填入數(shù)據(jù)? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? UsartReadCnt = UsartReadCnt + len;//記錄上次的數(shù)據(jù)個數(shù)if(UsartReadCnt >=3)//接收到可以處理的數(shù)據(jù)個數(shù)? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? UsartReadCnt =0;
? ? ? ? ? ? ? ? ? ? if(UsartReadBuff[0] ==0xaa&& UsartReadBuff[1] ==0x55)//判斷數(shù)據(jù)? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? if(UsartReadBuff[2] ==0x01)//? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? elseif(UsartReadBuff[2] ==0x00)
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? Invoke((newAction(() =>? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? button3.Text ="點亮";
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? label5.Text ="熄滅";
? ? ? ? ? ? ? ? ? ? ? ? ? ? })));
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }




?現(xiàn)在看發(fā)送
發(fā)送就只做字符串發(fā)送哈,,,16進制發(fā)送后期補上,,大家先吸收吸收現(xiàn)在的....




?執(zhí)行文件

我把16進制發(fā)送用到的函數(shù)放在這里,后期再回來加上

///<字符串轉(zhuǎn)16進制格式,不夠自動前面補零>//////</summary>///<param name="hexString"></param>///<returns></returns>privatestaticbyte[] strToToHexByte(String hexString)
? ? ? ? {
? ? ? ? ? ? int i;
? ? ? ? ? ? boolFlag =false;
? ? ? ? ? ? hexString = hexString.Replace("","");//清除空格if((hexString.Length %2) !=0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Flag =true;
? ? ? ? ? ? }
? ? ? ? ? ? if(Flag ==true)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? byte[] returnBytes =newbyte[(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 =newbyte[(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;
? ? ? ? ? ? }
? ? ? ? }

對了,其實上位機串口是有空閑時間中斷的(異常捕獲),只不過,我還沒細研究呢!!!