由于工作上的需要,经常要与USBCAN打交道,但厂家一般不会提供PYTHON的例子,于是自己摸索地写一个例子出来,以便在工作上随时可以使用PYTHON来测试CAN的功能。这里的例子是使用珠海创芯科技有限公司的USBCAN接口卡,他们提供一个ControlCAN.dll,也提供了一个.h文件,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#ifndef CONTROLCAN_H #define CONTROLCAN_H / / / / 文件版本:v2. 00 20150920 / / #include <cvidef.h> //使用CVI平台开发,请使用该语句。 / / 接口卡类型定义 #define VCI_USBCAN1 3 #define VCI_USBCAN2 4 #define VCI_USBCAN2A 4 #define VCI_USBCAN_E_U 20 #define VCI_USBCAN_2E_U 21 / / 函数调用返回状态值 #define STATUS_OK 1 #define STATUS_ERR 0 / * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 兼容ZLG的函数及数据类型 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * / / / 1.ZLGCAN 系列接口卡信息的数据类型。 typedef struct _VCI_BOARD_INFO{ unsigned short hw_Version; unsigned short fw_Version; unsigned short dr_Version; unsigned short in_Version; unsigned short irq_Num; unsigned char can_Num; char str_Serial_Num[ 20 ]; char str_hw_Type[ 40 ]; unsigned short Reserved[ 4 ]; } VCI_BOARD_INFO, * PVCI_BOARD_INFO; / / 2. 定义CAN信息帧的数据类型。 typedef struct _VCI_CAN_OBJ{ unsigned int ID ; unsigned int TimeStamp; unsigned char TimeFlag; unsigned char SendType; unsigned char RemoteFlag; / / 是否是远程帧 unsigned char ExternFlag; / / 是否是扩展帧 unsigned char DataLen; unsigned char Data[ 8 ]; unsigned char Reserved[ 3 ]; }VCI_CAN_OBJ, * PVCI_CAN_OBJ; / / 3. 定义初始化CAN的数据类型 typedef struct _VCI_INIT_CONFIG{ unsigned long AccCode; unsigned long AccMask; unsigned long Reserved; unsigned char Filter ; unsigned char Timing0; unsigned char Timing1; unsigned char Mode; }VCI_INIT_CONFIG, * PVCI_INIT_CONFIG; / / / / / / / / / new add struct for filter / / / / / / / / / typedef struct _VCI_FILTER_RECORD{ unsigned long ExtFrame; / / 是否为扩展帧 unsigned long Start; unsigned long End; }VCI_FILTER_RECORD, * PVCI_FILTER_RECORD; #define EXTERNC extern "C" EXTERNC unsigned long __stdcall VCI_OpenDevice(unsigned long DeviceType,unsigned long DeviceInd,unsigned long Reserved); EXTERNC unsigned long __stdcall VCI_CloseDevice(unsigned long DeviceType,unsigned long DeviceInd); EXTERNC unsigned long __stdcall VCI_InitCAN(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, PVCI_INIT_CONFIG pInitConfig); EXTERNC unsigned long __stdcall VCI_ReadBoardInfo(unsigned long DeviceType,unsigned long DeviceInd,PVCI_BOARD_INFO pInfo); EXTERNC unsigned long __stdcall VCI_SetReference(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,unsigned long RefType,void * pData); EXTERNC unsigned long __stdcall VCI_GetReceiveNum(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd); EXTERNC unsigned long __stdcall VCI_ClearBuffer(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd); EXTERNC unsigned long __stdcall VCI_StartCAN(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd); EXTERNC unsigned long __stdcall VCI_ResetCAN(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd); EXTERNC unsigned long __stdcall VCI_Transmit(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,PVCI_CAN_OBJ pSend,unsigned long Len ); EXTERNC unsigned long __stdcall VCI_Receive(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,PVCI_CAN_OBJ pReceive,unsigned long Len , int WaitTime); / * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 其他补充函数及数据结构描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * / / / USB - CAN总线适配器板卡信息的数据类型 1 ,该类型为VCI_FindUsbDevice函数的返回参数。 typedef struct _VCI_BOARD_INFO1{ unsigned long hw_Version; unsigned long fw_Version; unsigned long dr_Version; unsigned long in_Version; unsigned long irq_Num; unsigned char can_Num; unsigned char Reserved; char str_Serial_Num[ 8 ]; char str_hw_Type[ 16 ]; char str_Usb_Serial[ 4 ][ 4 ]; } VCI_BOARD_INFO1, * PVCI_BOARD_INFO1; / / USB - CAN总线适配器板卡信息的数据类型 2 ,该类型为VCI_FindUsbDevice函数的返回参数。为扩展更多的设备 typedef struct _VCI_BOARD_INFO2{ unsigned long hw_Version; unsigned long fw_Version; unsigned long dr_Version; unsigned long in_Version; unsigned long irq_Num; unsigned char can_Num; unsigned char Reserved; char str_Serial_Num[ 8 ]; char str_hw_Type[ 16 ]; char str_Usb_Serial[ 10 ][ 4 ]; } VCI_BOARD_INFO2, * PVCI_BOARD_INFO2; #define EXTERNC extern "C" EXTERNC unsigned long __stdcall VCI_GetReference2(unsigned long DevType,unsigned long DevIndex,unsigned long CANIndex,unsigned long Reserved,unsigned char * pData); EXTERNC unsigned long __stdcall VCI_SetReference2(unsigned long DevType,unsigned long DevIndex,unsigned long CANIndex,unsigned long RefType,unsigned char * pData); EXTERNC unsigned long __stdcall VCI_ConnectDevice(unsigned long DevType,unsigned long DevIndex); EXTERNC unsigned long __stdcall VCI_UsbDeviceReset(unsigned long DevType,unsigned long DevIndex,unsigned long Reserved); EXTERNC unsigned long __stdcall VCI_FindUsbDevice(PVCI_BOARD_INFO1 pInfo); EXTERNC unsigned long __stdcall VCI_FindUsbDevice2(PVCI_BOARD_INFO2 pInfo); #endif |
要调用这些函数才可以完成工作,下面就来创建一个例子,从CAN的通道0向通道1来发送一帧CAN数据,例子代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
#python3.6 32位 #https://blog.csdn.net/caimouse/article/details/51749579 #开发人员:蔡军生(QQ:9073204) 深圳 2018-3-25 # from ctypes import * VCI_USBCAN2A = 4 STATUS_OK = 1 class VCI_INIT_CONFIG(Structure): _fields_ = [( "AccCode" , c_ulong), ( "AccMask" , c_ulong), ( "Reserved" , c_ulong), ( "Filter" , c_ubyte), ( "Timing0" , c_ubyte), ( "Timing1" , c_ubyte), ( "Mode" , c_ubyte) ] class VCI_CAN_OBJ(Structure): _fields_ = [( "ID" , c_uint), ( "TimeStamp" , c_uint), ( "TimeFlag" , c_ubyte), ( "SendType" , c_ubyte), ( "RemoteFlag" , c_ubyte), ( "ExternFlag" , c_ubyte), ( "DataLen" , c_ubyte), ( "Data" , c_ubyte * 8 ), ( "Reserved" , c_ubyte * 3 ) ] CanDLLName = 'ControlCAN.dll' #DLL是32位的,必须使用32位的PYTHON canDLL = windll.LoadLibrary(CanDLLName) print (CanDLLName) ret = canDLL.VCI_OpenDevice(VCI_USBCAN2A, 0 , 0 ) print (ret) if ret ! = STATUS_OK: print ( '调用 VCI_OpenDevice出错\r\n' ) #初始0通道 vci_initconfig = VCI_INIT_CONFIG( 0x80000008 , 0xFFFFFFFF , 0 , 2 , 0x00 , 0x1C , 0 ) ret = canDLL.VCI_InitCAN(VCI_USBCAN2A, 0 , 0 , byref(vci_initconfig)) if ret ! = STATUS_OK: print ( '调用 VCI_InitCAN出错\r\n' ) ret = canDLL.VCI_StartCAN(VCI_USBCAN2A, 0 , 0 ) if ret ! = STATUS_OK: print ( '调用 VCI_StartCAN出错\r\n' ) #初始1通道 ret = canDLL.VCI_InitCAN(VCI_USBCAN2A, 0 , 1 , byref(vci_initconfig)) if ret ! = STATUS_OK: print ( '调用 VCI_InitCAN 1 出错\r\n' ) ret = canDLL.VCI_StartCAN(VCI_USBCAN2A, 0 , 1 ) if ret ! = STATUS_OK: print ( '调用 VCI_StartCAN 1 出错\r\n' ) #通道0发送数据 ubyte_array = c_ubyte * 8 a = ubyte_array( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 64 ) ubyte_3array = c_ubyte * 3 b = ubyte_3array( 0 , 0 , 0 ) vci_can_obj = VCI_CAN_OBJ( 0x0 , 0 , 0 , 1 , 0 , 0 , 8 , a, b) ret = canDLL.VCI_Transmit(VCI_USBCAN2A, 0 , 0 , byref(vci_can_obj), 1 ) if ret ! = STATUS_OK: print ( '调用 VCI_Transmit 出错\r\n' ) #通道1接收数据 a = ubyte_array( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) vci_can_obj = VCI_CAN_OBJ( 0x0 , 0 , 0 , 1 , 0 , 0 , 8 , a, b) ret = canDLL.VCI_Receive(VCI_USBCAN2A, 0 , 1 , byref(vci_can_obj), 1 , 0 ) print (ret) while ret < = 0 : print ( '调用 VCI_Receive 出错\r\n' ) ret = canDLL.VCI_Receive(VCI_USBCAN2A, 0 , 1 , byref(vci_can_obj), 1 , 0 ) if ret > 0 : print (vci_can_obj.DataLen) print ( list (vci_can_obj.Data)) #关闭 canDLL.VCI_CloseDevice(VCI_USBCAN2A, 0 ) |
运行结果输出如下:
ControlCAN.dll
1
1
8
[1, 2, 3, 4, 5, 6, 7, 64]
可以看到从通道1里收通道0发过来的数据,达到这个程序的目的。
以上这篇使用python来调用CAN通讯的DLL实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/caimouse/article/details/79692118