RS-232/UART
RS-232 UART是電腦最古早的通訊介面之一,即使現在買桌上型電腦都還會有保留RS-232,而且現在很多MCU的控制介面,UART都還是基本會支援的標準協定,差異主要是差異在電位的高低,最早期的RS-232為12V, 現在MCU可能都是3.3V or 1.8V,如果想知道Serial Communication可以參考MIPI RFFE Introduction and two wire communication/serial communication UART, I2C 。
VISA Virtual Instrumentation Software Architecture
工作上常常需要控制儀器與待測物來完成工作,早期的儀器通訊介面大多是RS-232或GPIB IEEE 488.2,而且為了讓每使用者在使用不同儀器都有類似的語法都會支援SCPI Standard Commands for Programmable Instruments指令,安裝VISA COM(Virtual Instrumentation Software Architecture) Library大部分常見的程式語言就可以使用這個'VISA COM Library來進行儀器控制。
Excel VBA RS-232 Control via VISA
Excel本身有內建VBA (VB6的語法結構),平常工作我經常使用Excel VBA來進行儀器控制,這可以在Keysight或NI的網站上找到不少資源,另外VISA COM因為相容之前RS-232所以也可以透過VISA COM直接對RS-232進行控制,因為VBA(VB6)不能使用類似C# or VB.NET直接使用SYSTEM.IO.PORTS來對COM Port進行存取,網路上還有一些文章有教學如何用Excel VBA來取存RS232,但有COM 編號要在4以下的限制,而且內容較複雜,這裡我介紹如何用Excel VBA + VISA COM Library進行UART傳輸跟一些小技巧。
首先要安裝VISA COM Library,可以安裝Keysight[2] or NI[3]都可以,細節部分[4] 7 steps to using VBA in Excel to control routing in test automation ,安裝我們在Excel拉出一個Command Button然後輸入以下程式碼。
Private Sub CommandButton1_Click()
'myCOM為虛擬儀器資源
Dim myCOM As VisaComLib.FormattedIO488
're_myCOM是對應的控制介面管理
Dim rm_myCOM As VisaComLib.ResourceManager
Set myCOM = New VisaComLib.FormattedIO488
Set rm_myCOM = New VisaComLib.ResourceManager
' 開啟COM PORT資源 這個範例是4, 但可以到99沒問題
Set myCOM.IO = rm_myCOM.Open("ASRL4::INSTR")
' RS232是VISA COM對應Serial Port資源
Dim RS232 As ISerial
Set RS232 = myCOM.IO
'設定BaudRate還有硬體控制
RS232.BaudRate = 9600
RS232.FlowControl = ASRL_FLOW_NONE
myCOM.IO.TerminationCharacter = 10
myCOM.IO.TerminationCharacterEnabled = True
'定義傳送的變數
Dim in_str As String
Dim out_str As String
out_str = Chr(72) & Chr(69) & Chr(76) & Chr(76) & Chr(79)
'傳送字串 H, E, L, L, O
myCOM.WriteString out_str
'讀取字串
in_str = myCOM.ReadString
MsgBox in_str & " Len = " & Len(in_str) & " last byte dec =" & Asc(Mid(in_str, Len(in_str), 1))
RS232.Close
End Sub
我們將UART TX與RX用Jumper接起來測試看看執行結果,這個結果我們是發送了out_str這字串,字串的內容是由ASCII編碼組成,傳送72, 69, 76, 76, 79 這5個bytes的資料,ASCII編碼就是HELLO。
out_str = Chr(72) & Chr(69) & Chr(76) & Chr(76) & Chr(79)
但回傳了字串Strin長度卻是6 bytes,最後一各byte為DEC 10,對應的ASCII為換行字元,有點算是如果你用超級終端機Hyper Terminal 輸入HELLO後按下的Enter鍵的行為。
因為VISA COM WriteString這函數原本就是設計給儀器控制用的,而儀器控制會以換行字元LF來判定指令是否結束或資料是否結束,所以WriteString會自動帶上LF字元,另外ReadString如果沒有讀到LF字元在一定時間內會認為讀取失敗。
但有些MCU指令為了節省指令長度,會以HEX檔案格式傳輸,而不是以文字傳輸,舉例來說我要對MCU發送一個255 0xFF的訊息,如果傳輸byte格式只需要一個byte就可以完成,但如果以文字傳輸就需要FF兩個字元也就是兩個bytes才能完成。
這樣的傳輸模式就不會以換行字元LF或其他特定的字元當作訊息,因為LF 0x0A需要拿來當作資料的訊息,不然會無法分辨0x0A是指令結束還是資料內容。
我們將Write的部分用myCOM.IO.WriteString取代原本myCOM.Writestring,讀取部分也是從原本myCOM.ReadString改成myCOM.IO.ReadString。
'Write
Dim i As Integer
For i = 1 To Len(out_str)
myCOM.IO.WriteString Mid(out_str, i, 1)
Next i
'Read
Sleep 10
Dim buffer_count As Integer
'確認RX Buffer上是否有值與多少個Bytes
buffer_count = RS232.BytesAvailable
in_str = myCOM.IO.ReadString(buffer_count)
執行結果就可以正確HELLO沒有LF的字串。
Send Any Byte Data
但是這樣傳輸還是會遇到一個問題,myCOM.IO.WriteString的輸入資料是對照ASCII,所以有些字元傳送會發生問題,例如0x00空字元。
這個問題在某一天晚上讓我花了不少時間,也是我想寫這一篇的原因,寫入部分用myCOM.IO.Write (bytes(),1)來傳送,傳送0, 8, 128, 255,主要關鍵在讀取的部分,因為傳送是用BYTE,所以讀取應該也是用Byte的資料格式讀取,但一開始用Byte無法得到正確的結果,後來發現要用Variant or String的格式才能正確把資料讀入,然後再用AscB()函數轉成Byte的資料
Dim in_str As String
Dim out_str As String
Dim out_byte(3) As Byte
Dim write_buf(0) As Byte
Dim i As Integer
Dim w_index As Long
out_byte(0) = 0
out_byte(1) = 8
out_byte(2) = 128
out_byte(3) = 255
For i = 0 To UBound(out_byte)
write_buf(0) = out_byte(i)
w_index = myCOM.IO.Write(write_buf, 1)
Next i
'Read
Sleep 20
Dim buffer_count As Integer
Dim read_bf As String
Dim test_byte(10) As Byte
Dim in_bytes() As Byte
'確認RX Buffer上是否有值與多少個Bytes
buffer_count = RS232.BytesAvailable
ReDim in_bytes(buffer_count)
For i = 1 To buffer_count
' 讀取資料必須要為String or Variant
read_bf = myCOM.IO.Read(1)
'ASCB將字元轉回Byte
in_bytes(i) = AscB(read_bf)
in_str = in_str & i & " = " & in_bytes(i) & " : "
Next i
MsgBox in_str
執行結果傳送0x00, 0x10, 0x80, 0xFF四個bytes,然後正確讀取顯示。
Serial Port (UART)現在都還蠻常見的,很多程式語言也都有支援,但大多時候不需要太複雜的自動控制,要同時控制儀器,UART Device與數據處理,Excel VBA是個很好的工具,因為Excel內建很多實用切熟悉的函數可以使用,而且每個欄位都是一個變數空間,而且電腦幾乎都有Excel可以針對不同的需求直接修改內容,另外如果對Excel VBA儀器控制有興趣也可以參考[7]Keysight的網站也有很多相關資源。
Reference
完整程式碼
'Copy and Paste Below Code to your Excel
Private Sub CommandButton3_Click()
Dim myCOM As VisaComLib.FormattedIO488
Dim rm_myCOM As VisaComLib.ResourceManager
Set myCOM = New VisaComLib.FormattedIO488
Set rm_myCOM = New VisaComLib.ResourceManager
Set myCOM.IO = rm_myCOM.Open("ASRL4::INSTR")
Dim RS232 As ISerial
Set RS232 = myCOM.IO
RS232.BaudRate = 9600
RS232.FlowControl = ASRL_FLOW_NONE
myCOM.IO.TerminationCharacter = 10
myCOM.IO.TerminationCharacterEnabled = True
Dim in_str As String
Dim out_str As String
Dim out_byte(3) As Byte
Dim write_buf(0) As Byte
Dim i As Integer
Dim w_index As Long
out_byte(0) = 0
out_byte(1) = 8
out_byte(2) = 128
out_byte(3) = 255
For i = 0 To UBound(out_byte)
write_buf(0) = out_byte(i)
w_index = myCOM.IO.Write(write_buf, 1)
Next i
'Read
Sleep 20
Dim buffer_count As Integer
Dim read_bf As String
Dim test_byte(10) As Byte
Dim in_bytes() As Byte
'確認RX Buffer上是否有值與多少個Bytes
buffer_count = RS232.BytesAvailable
ReDim in_bytes(buffer_count)
For i = 1 To buffer_count
' 讀取資料必須要為String or Variant
read_bf = myCOM.IO.Read(1)
'ASCB將字元轉回Byte
in_bytes(i) = AscB(read_bf)
in_str = in_str & i & " = " & in_bytes(i) & " : "
Next i
MsgBox in_str
RS232.Close
End Sub
謝謝分享, 但是那個接頭照片是VGA, RS232是DB9, 所以需要換一下
回覆刪除高手....手邊主機版也沒有DB9..想說長的很像魚目混珠了一下,還是被發現了
刪除