FTDI是一家生產USB to GPIO/UART/I2C/SPI 等的轉換IC的公司,很容易在開發版上面看到它的身影,FTDI網站上也有提供一些example code,[1] "Our thanks go to Bob Freeth for providing this VB6 example of using the FT2232C MPSSE for SPI communication with a MAX187 ADC",因為Excel VBA本身也是VB核心,應該是可以直接拿來參考使用。
直接複製是可以使用正常在VBA上面執行,但後來發現他無法在Excel 64x上面執行,再引入D2XXX.DLL Declare陳述句中會出現紅色的錯誤。
'==============================
'CLASSIC INTERFACE DECLARATIONS
'==============================
Public Declare Function FT_ListDevices Lib "FTD2XX.DLL" ( _
ByVal arg1 As Long, _
ByVal arg2 As String, _
ByVal dwFlags As Long) As Long
Public Declare Function FT_GetNumDevices Lib "FTD2XX.DLL" Alias "FT_ListDevices" ( _
ByRef arg1 As Long, _
ByVal arg2 As String, _
ByVal dwFlags As Long) As Long
Public Declare Function FT_Open Lib "FTD2XX.DLL" ( _
ByVal intDeviceNumber As Integer, _
ByRef lngHandle As Long) As Long
PtrSafe 大部分情況下工作正常
上網查了一下[2] "64 位元 Visual Basic for Applications 概觀"原來Excel 64位元一些變數宣告需要修改變更一下,看了一些其他網頁的資料,大部分時候只需要在Sub or Function前面加入PtrSafe就可以正常執行,至少編譯器不會顯示錯誤。
'==============================
'CLASSIC INTERFACE DECLARATIONS
'==============================
#If VBA7 Then
Public Declare PtrSafe Function FT_ListDevices Lib "FTD2XX.DLL" ( _
ByVal arg1 As Long, _
ByVal arg2 As String, _
ByVal dwFlags As Long) As Long
#Else
Public Declare Function FT_ListDevices Lib "FTD2XX.DLL" ( _
ByVal arg1 As Long, _
ByVal arg2 As String, _
ByVal dwFlags As Long) As Long
#End If
但改完發現結果不對,一樣的程序在Excel VBA 32-bit上面跑是正常的,但在64-bit上面就是不正常,在看了一下網路上的資料竟然有書專門在談論這個[3] Excel 2019 Power Programming with VBA,但從Microsfot的網站上[2]提到指標Pointer與控制代碼Handle在VBA7 64-bit下可能會因為資料長度不一樣無法正確執行。
由於 VBA 第 6 版或更早的版本並沒有指標或控制代碼的特定資料類型,因此會使用 Long 資料類型 ( 32 位元 4 個位元組的資料類型),來參考指標和控制代碼。 在 64 位元環境中,指標和控制代碼是 8 位元組 64 位元的數量。 32 位元資料類型中,無法保存這些 64 位元數量。
查一下[4] D2XX Programmer's Guide先把Handle部分找出來並把變數型態由原本Long改成LongPtr,例如以下兩個函數FT_Open and FT_Write,修改後跑起來就正常了,但每個有用到的都要去修改檢查。
Public Declare PtrSafe Function FT_Open Lib "FTD2XX.DLL" ( _
ByVal intDeviceNumber As Integer, _
ByRef lngHandle As LongPtr) As Long.
Public Declare PtrSafe Function FT_Write Lib "FTD2XX.DLL" ( _
ByVal lngHandle As LongPtr, _
ByVal lpszBuffer As String, _
ByVal lngBufferSize As Long, _
ByRef lngBytesWritten As Long) As Long
.
Update FTDI Driver and Summary
後來在不同電腦交叉測試發現,到FTDI 下載新的Driver ( setup executable),一樣是64-bit VBA7但跑起來是正常的,但說實在只有跑幾個函數不知道是不是其它函數需要修改就是了,所以最安全與最艱單的做法是安裝32-bit的版本,MicroSoft的官方指南中也提到[5] "選擇 64 位元或 32 位元版的 Office" ,兼容之前的ActiveX or COM元件的確是每個軟體選擇要不要進版的一個原因,但這也算是一種人性,改了如果動不了又可能程式已經是好久好久的前輩弄得,早就不知道消失到哪去了,突然改了不會動找誰求救阿。
選擇 32 位元版本的理由
您的 32 位元 COM 增益集沒有對應的 64 位元增益集。 您可以繼續在 64 位元 Windows 的 32 位元 Office 中執行 32 位元 COM 增益集, 也可以嘗試連絡 COM 增益集廠商,要求對方提供 64 位元版本。
您使用的 32 位元控制項沒有對應的 64 位元控制項。 您可以在 32 位元 Office 中繼續執行 32 位元控制項,例如 Microsoft Windows 通用控制項 (Mscomctl.ocx、comctl.ocx) 或任何現有的協力廠商 32 位元控制項。
您的 VBA 程式碼使用 Declare 陳述式。 除非您針對指標和控點以 Declare 陳述式呼叫 long 等使用 32 位元資料類型的 Windows API,否則無論您使用的是 64 位元或 32 位元,通常都不需要變更 VBA 程式碼。 在大部分情況下,將 PtrSafe 新增到 Declare,並以 LongPtr 取代 long,就可讓 Declare 陳述式同時與 32 位元和 64 位元相容。 不過,如果是沒有可用於 Declare 的 64 位元 API 的少數情況,您就無法這麼做。 如需 VBA 要在 64 位元 Office 上執行所需之必要變更的詳細資訊,請參閱 64 位元 Visual Basic for Applications 概觀。
Reference
[1] Our thanks go to Bob Freeth for providing this VB6 example of using the FT2232C MPSSE for SPI communication with a MAX187 ADC.
[2] 64 位元 Visual Basic for Applications 概觀
[3] Excel 2019 Power Programming with VBA
[4] D2XX Programmer's Guide
[5] 選擇 64 位元或 32 位元版的 Office