[VB.Net]Serialport 接收溢位 超過127 (7FH) 顯示 "?" 3FH 的錯誤解決方法
最近在寫dsPIC專題使用UART與電腦通訊,在程式上遇到了一個之前沒遇過的問題。
就是一般在通訊使用上接收回來的值都介於00H~7FH,由 80H 到 FFH 共 128 個字元,一般稱為『擴充字元』,這 128 個擴充字元是由 IBM 制定的,並非標準的 ASCII 碼。這些字元是用來表示框線、音標和其他歐洲非英語系的字母。
一般通訊設定Serialport時是不會設定Serialport.Encoding,而使用SerialPort1.ReadExisting()來接收資料。
在這個時候只要超過7FH的值都會被判斷為ASCII的?,解析成16進制就會變成3fH或十進制的63
從前的程式碼如下:
用通訊擷取軟體可以看到傳送出41的命令,回傳01,00,00,00,89,37,A9的值
然後下列是軟體收到的訊息,傳送A的ASCII(41H),結果接收到如下圖01,00,00,00,3f,37,3f
原因在於接受到的倒數第一個和倒數第三個數值都超過了7FH,所以會顯示3f的訊息出來。在程式中顯示的ASCII為? ,也就是無法辨識(溢位)
問題點就如開頭所講的80H~FFH是非標準的ASCII(擴充字元),所以我們在串列埠要做一些設定。
首先在開啟Serialport前要先設定
SerialPort1.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1")
在ASCII轉HEX
Dim ascii() As Byte = System.Text.Encoding.Default.GetBytes(asciiString)
要改成
Dim ascii() As Byte = System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(asciiString)
參考網址(我查到這個指令的網址):
http://www.dreamincode.net/forums/topic/79400-receive-hex-data-through-serial-port/
http://msmvps.com/blogs/peplluis/archive/2008/10/15/system-io-ports-serialport-conversiones-y-codificaciones.aspx
在第一組網址呢是要我們使用System.Text.Encoding.GetEncoding("Windows-1252")
但是後來我去查了一下,這個指令僅支援80H~9FH(http://en.wikipedia.org/wiki/ISO/IEC_8859-1)
所以我們就使用 System.Text.Encoding.GetEncoding("iso-8859-1")
如此收到的命令,就跟我們再擷取軟體收到的命令是相同的了。
打完收工
就是一般在通訊使用上接收回來的值都介於00H~7FH,由 80H 到 FFH 共 128 個字元,一般稱為『擴充字元』,這 128 個擴充字元是由 IBM 制定的,並非標準的 ASCII 碼。這些字元是用來表示框線、音標和其他歐洲非英語系的字母。
一般通訊設定Serialport時是不會設定Serialport.Encoding,而使用SerialPort1.ReadExisting()來接收資料。
在這個時候只要超過7FH的值都會被判斷為ASCII的?,解析成16進制就會變成3fH或十進制的63
從前的程式碼如下:
'開啟PORT Private Sub btnOpenPort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenPort.Click SerialPort1.PortName = cmbPort.SelectedItem.ToString 'COMPORT Name SerialPort1.BaudRate = 9600 SerialPort1.Parity = Parity.None SerialPort1.DataBits = 8 SerialPort1.StopBits = StopBits.One SerialPort1.Open() '開啟串列埠 End Sub 'ASCII轉HEX(另外一篇有說明) Public Function AsciiStringToHexString(ByVal asciiString As String) As Array Dim ascii() As Byte = System.Text.Encoding.Default.GetBytes(asciiString) Dim count As Integer = ascii.Length Dim hexArray(count - 1) As String For idx As Integer = 0 To count - 1 hexArray(idx) = ascii(idx).ToString("x2") Next Return hexArray 'String.Join(" ", hexArray) End Function '時間延遲 Public Sub TimeDelay(ByVal DT As Integer) Dim StartTick As Integer StartTick = Environment.TickCount() '開始計數前的Tick Do If Environment.TickCount() - StartTick >= DT Then Exit Do Application.DoEvents() '處理佇列中的訊息 Loop End Sub '******************************************** '傳送按鈕的Click事件 '使用Write方法送出資料 '******************************************** Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click SerialPort1.ReadExisting() Dim aa As String Dim bb() As String SerialPort1.Write(txtSend.Text) TimeDelay(500) aa = SerialPort1.ReadExisting() bb = AsciiStringToHexString(aa) txtReceive.Text = String.Join(",", bb) End Sub
用通訊擷取軟體可以看到傳送出41的命令,回傳01,00,00,00,89,37,A9的值
然後下列是軟體收到的訊息,傳送A的ASCII(41H),結果接收到如下圖01,00,00,00,3f,37,3f
原因在於接受到的倒數第一個和倒數第三個數值都超過了7FH,所以會顯示3f的訊息出來。在程式中顯示的ASCII為? ,也就是無法辨識(溢位)
問題點就如開頭所講的80H~FFH是非標準的ASCII(擴充字元),所以我們在串列埠要做一些設定。
首先在開啟Serialport前要先設定
SerialPort1.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1")
在ASCII轉HEX
Dim ascii() As Byte = System.Text.Encoding.Default.GetBytes(asciiString)
要改成
Dim ascii() As Byte = System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(asciiString)
參考網址(我查到這個指令的網址):
http://www.dreamincode.net/forums/topic/79400-receive-hex-data-through-serial-port/
http://msmvps.com/blogs/peplluis/archive/2008/10/15/system-io-ports-serialport-conversiones-y-codificaciones.aspx
在第一組網址呢是要我們使用System.Text.Encoding.GetEncoding("Windows-1252")
但是後來我去查了一下,這個指令僅支援80H~9FH(http://en.wikipedia.org/wiki/ISO/IEC_8859-1)
所以我們就使用 System.Text.Encoding.GetEncoding("iso-8859-1")
'開啟PORT Private Sub btnOpenPort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpenPort.Click '====設定編碼==== SerialPort1.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1") SerialPort1.PortName = cmbPort.SelectedItem.ToString 'COMPORT Name SerialPort1.BaudRate = 9600 SerialPort1.Parity = Parity.None SerialPort1.DataBits = 8 SerialPort1.StopBits = StopBits.One SerialPort1.Open() '開啟串列埠 End Sub 'ASCII轉HEX(另外一篇有說明) Public Function AsciiStringToHexString(ByVal asciiString As String) As Array Dim ascii() As Byte = System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(asciiString) '修改後的編碼定義 Dim count As Integer = ascii.Length Dim hexArray(count - 1) As String For idx As Integer = 0 To count - 1 hexArray(idx) = ascii(idx).ToString("x2") Next Return hexArray 'String.Join(" ", hexArray) End Function '時間延遲 Public Sub TimeDelay(ByVal DT As Integer) Dim StartTick As Integer StartTick = Environment.TickCount() '開始計數前的Tick Do If Environment.TickCount() - StartTick >= DT Then Exit Do Application.DoEvents() '處理佇列中的訊息 Loop End Sub '******************************************** '傳送按鈕的Click事件 '使用Write方法送出資料 '******************************************** Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click SerialPort1.ReadExisting() Dim aa As String Dim bb() As String SerialPort1.Write(txtSend.Text) TimeDelay(500) aa = SerialPort1.ReadExisting() bb = AsciiStringToHexString(aa) txtReceive.Text = String.Join(",", bb) End Sub
如此收到的命令,就跟我們再擷取軟體收到的命令是相同的了。
打完收工
感謝!很有用喔.........
回覆刪除