1、概述
Virtual CAN Interface (VCI) 函數庫是專門為ZLGCAN 設備在PC 上使用而提供的應用程序接口。庫里的函數從ControlCAN.dll 中導出,在LabVIEW7.0 中可以直接使用這些庫函數而無需額外的操作。VCI 函數的使用流程如圖 1.1 所示。
[align=center]

圖 1.1 VCI 函數使用流程[/align]
2、使用VCI 函數
2.1 數據結構
VCI 函數庫中定義了一些數據結構用于數據交換,在使用VCI 函數前應該先創建這些數據結構。在LabVIEW 中創建這些結構時應該使用簇——Cluster。一個簇就是一個由若干不同的數據類型的成員組成的集合體,類似于C 語言中的結構。其成員可以是任意的數據類型,但必須都是控件或都是顯示件。成員的邏輯順序是由它們被放入簇的先后順序決定的。
2.1.1 VCI_BOARD_INFO 結構
VCI_BOARD_INFO 結構體包含ZLGCAN 系列接口卡的設備信息。結構體將在VCI_ReadBoardInfo 函數中被填充。
typedef struct _VCI_BOARD_INFO {
USHORT hw_Version;
USHORT fw_Version;
USHORT dr_Version;
USHORT in_Version;
USHORT irq_Num;
BYTE can_Num;
CHAR str_Serial_Num[20];
CHAR str_hw_Type[40];
USHORT Reserved[4];
} VCI_BOARD_INFO, *PVCI_BOARD_INFO;
[align=center]

圖 2.1 VCI_BOARD_INFO 結構[/align]
2.1.2 VCI_CAN_OBJ 結構
VCI_CAN_OBJ 結構體在VCI_Transmit 和VCI_Receive 函數中被用來傳送CAN信息幀。
typedef struct _VCI_CAN_OBJ {
UINT ID;
UINT TimeStamp;
BYTE TimeFlag;
BYTE SendType;
BYTE RemoteFlag;
BYTE ExternFlag;
BYTE DataLen;
BYTE Data[8];
BYTE Reserved[3];
} VCI_CAN_OBJ, *PVCI_CAN_OBJ;
[align=center]

圖 2.2 VCI_CAN_OBJ 結構[/align]
2.1.3 VCI_CAN_STATUS 結構
VCI_CAN_STATUS 結構體包含CAN 控制器狀態信息。結構體將在VCI_ReadCanStatus函數中被填充。
typedef struct _VCI_CAN_STATUS {
UCHAR ErrInterrupt;
UCHAR regMode;
UCHAR regStatus;
UCHAR regALCapture;
UCHAR regECCapture;
UCHAR regEWLimit;
UCHAR regRECounter;
UCHAR regTECounter;
DWORD Reserved;
} VCI_CAN_STATUS, *PVCI_CAN_STATUS;
[align=center]

圖 2.3 VCI_CAN_STATUS 結構[/align]
2.1.4 VCI_ERR_INFO 結構
VCI_ERR_INFO結構體用于裝載VCI庫運行時產生的錯誤信息。結構體將在VCI_ReadErrInfo函數中被填充。
typedef struct _ERR_INFO {
UINT ErrCode;
BYTE Passive_ErrData[3];
BYTE ArLost_ErrData;
} VCI_ERR_INFO, *PVCI_ERR_INFO;
[align=center]

圖 2.4 VCI_ERR_INFO 結構[/align]
2.1.5 VCI_INIT_CONFIG 結構
VCI_INIT_CONFIG 結構體定義了初始化CAN 的配置。結構體將在VCI_InitCan 函數中被填充。
typedef struct _INIT_CONFIG {
DWORD AccCode;
DWORD AccMask;
DWORD Reserved;
UCHAR Filter;
UCHAR Timing0;
UCHAR Timing1;
UCHAR Mode;
} VCI_INIT_CONFIG, *PVCI_INIT_CONFIG;
[align=center]

圖 2.5 VCI_INIT_CONFIG 結構[/align]
下面以VCI_CAN_OBJ 結構為例,在LabVIEW7.0 中創建VCI_CAN_OBJ 結構。先在Array&Cluster 控件子模板選擇一個簇的空殼放到前面板上,將其命名為VCI_CAN_OBJ,然后根據需要放置的控件多少用定位工具調整簇空殼的大小;按照VCI_CAN_OBJ 結構成員的順序,從Numeric 控件子模板中取Numeric Indicator 控件或從前面板上移動控件到簇的空殼中,并按圖 2.6 將各Numeric Indicator 控件重命名。
[align=center]

圖 2.6 在前面板上創建VCI_CAN_OBJ 結構的簇[/align]
此時,簇殼內的成員的數據類型都為默認的Double 類型。在簇殼內的邊框上彈出快捷菜單,選擇Representation。在下一級子菜單中選擇與VCI_CAN_OBJ 結構成員類型一致的類型。
[align=center]

圖 2.7 設置成員類型[/align]
2.2 調用VCI 庫函數
在LabVIEW 中調用VCI 庫函數的過程比較簡單。LabVIEW 在Advanced 函數子模板中提供了Calling Library Function Node,只要知道動態連接庫里被導出的函數名稱及其參數,就可以通過Calling Library Function Node 調用。ZLG VCI 函數庫已經提供了庫里的函數聲明,因此,在LabVIEW 中使用VCI 函數庫將通過Calling Library Function Node 來實現。
以調用VCI_OpenDevice 函數為例。在LabVIEW 圖形代碼窗口中放上調用庫函數節點,用鼠標雙擊節點或使用快捷菜單命令Configure 彈出如圖 2.8 所示的對話框。
[align=center]

圖 2.8 調用庫函數1[/align]
單擊Browse…按鈕,打開一個文件對話框,找到ControlCAN.dll 文件。或者直接輸入庫文件路徑和名稱。
在Function Name 下拉列表框中照到VCI_OpenDevice 函數。或直接輸入函數名。
[align=center]

圖 2.9 調用庫函數2[/align]
在Calling Conventions 下拉列表框中選中stdcall(WINAPI),因為VCI 庫函數使用的是stdcall 調用約定。
Parameter 框中的return type 不變。Type 框中選Numeric。Data Type 框中選Unsigned 32-bitInterger。即指定返回32 位整形數。
單擊Add a Parameter After 按鈕,Parameter 框中的選項變為圖 2.10 所示。將缺省值agr1改為DevType,因為在VCI_OpenDevice 函數聲明中定義了參數DevType。
[align=center]

圖 2.10 調用庫函數3[/align]
Type 框中選Numeric,并在Data Type 框中選Unsigned 32-bit Integer。表示將編程時指定的LabVIEW 數據類型為32 位無符號整型。Pass 框中選擇Value。
同樣,按以上步驟添加DevIndex、Reserved 參數。
單擊OK 按鈕退出這個對話框。調用庫函數節點變為圖 2.11 所示中的情況。圖中的參數端口由上到下分別為return type、DevType、DevIndex 和Reserved。每個端口均有一個輸入端和一個輸出端,左邊的端口為輸入端,右邊的端口位輸出端。因為第一個端口是函數的返回值,所以沒有輸入端,在圖中可以看到其輸入端為填充的藍色。其他端口則是函數的參數,如果參數的類型是指針的話,可以通過參數的輸出端輸出數據。在其他情況下,不需要使用參數的輸出端。
[align=center]

圖 2.11 調用庫函數程序框圖[/align]
2.3 應用示例
應用示例Demo 演示了在LabVIEW7.0 下如何使用VCI 庫函數。其界面如圖 2.12 所示。
[align=center]

圖 2.12 demo 界面[/align]
在Demo 中實現了數據的收發,并將在CAN總線上收發的數據在列表示圖中顯示。Demo程序當中有3 個主要的While 循環:主循環、發送數據循環和接收數據循環。這三個循環是并行運行的。其中,主循環處理與用戶交互的界面,并通過用戶事件TREvent 與發送數據循環和接收數據循環通信。
在主循環中使用事件驅動機制處理用戶在前面板的操作。打開設備的程序框圖如圖2.13 所示。在圖中調用VCI_OpenDevice 函數打開設備,如果打開成功,則調用VCI_InitCAN函數初始化設備,成功的話就處理一下前面板控件的狀態。
[align=center]

圖 2.13 打開設備框圖[/align]
圖 2.14 所示是接收數據的程序框圖。接收數據的過程是在一個while 循環中,這個循環在程序已開始時就一直運行,直到前面板上的stop 按鈕被按下并在其Value Change 事件中使stop2 的值變為False 時才停止。在循環當中,只有設備已經啟動時才會進行讀操作。在Demo 中VCI_Reveive 函數一次只讀取一幀,輸出的數據保存到VCI_CAN_OBJ_R 結構中,如果VCI_Reveive 函數執行成功的話,就把接收到的數據通過事件傳遞給主循環處理。
[align=center]

圖 2.14 接收數據[/align]
發送數據的過程與接收數據的過程相似。當前面板上的Transmit 按鈕被按下時,才會把VCI_CAN_OBJ_T 結構中的數據通過VCI_Transmit 函數發送到CAN 總線上。發送成功后,生成一個TREvent 事件,并通過這個事件把VCI_CAN_OBJ_T 結構的內容傳遞給主循環顯示。
[align=center]

圖 2.15 發送數據[/align]
3、VCI 函數調用參考
在LabVIEW 中使用Calling Library Function Node 調用VCI 庫函數的配置如下各表所示。
3.1 VCI_OpenDevice
3.2 VCI_CloseDevice
3.3 VCI_InitCan
[align=center]

[/align]
3.4 VCI_ReadBoardInfo
3.5 VCI_ReadErrInfo
[align=center]

[/align]
3.6 VCI_ReadCanStatus
3.7 VCI_GetReference
[align=center]

[/align]
3.8 VCI_SetReference
3.9 VCI_GetReceiveNum
3.10 VCI_ClearBuffer
3.11 VCI_StartCAN
3.12 VCI_ResetCAN
[align=center]

[/align]
3.13 VCI_Transmit
3.14 VCI_Receive
[align=center]

[/align]