2020年6月6日 星期六

如何用Excel VBA控制COM Port / EXCEL VBA RS-232/UART Control Via VISA COM Library

 
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

2 則留言:

  1. 謝謝分享, 但是那個接頭照片是VGA, RS232是DB9, 所以需要換一下

    回覆刪除
    回覆
    1. 高手....手邊主機版也沒有DB9..想說長的很像魚目混珠了一下,還是被發現了

      刪除

熱門文章