简单介绍使用python来调用CAN通讯的DLL实现方法,以及使用过程中遇到的错误。这里使用的是沈阳广成科技有限公司的USBCAN接口卡,上位机调用他们提供一个ECanVci.dll文件,如下:
canDLL = ctypes.WinDLL(“D:/ECanVci.dll”) #调用can的dll文件,网上方法有很多种,这里是直接将dll文件放在D盘根目录。
:
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)
]
VCI_INIT_CONFIG结 构 体定义 ECAN 系 列 接 口 卡 的 初始化信息。
通过改变 Timing0 和 Timing1 的值来设定CAN的波特率。
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)
]
VCI_CAN_OBJ结构体表示帧的数据结构。在发送函数Transmit和接收函数Receive中被用来传送CAN信息帧。结构体的具体定义如下:
ID:报文帧ID。
TimeStamp:接收到信息帧时的时间标识,从CAN控制器初始化开始计时,单位微秒。
TimeFlag:是否使用时间标识,为1时TimeStamp有效,TimeFlag和TimeStamp只在此帧为接收帧时有意义。
SendType:发送帧类型。=0时为正常发送,=1时为单次发送(不自动重发),=2时为自发自收(用于测试CAN卡是否损坏),=3时为单次自发自收(只发送一次,用于自测试),只在此帧为发送帧时有意义。
RemoteFlag:是否是远程帧。=0时为数据帧,=1时为远程帧。
ExternFlag:是否是扩展帧。=0时为标准帧(11位帧ID),=1时为扩展帧(29位帧ID)。
DataLen:数据长度DLC(<=8),即Data的长度。
Data:CAN报文的数据。空间受DataLen的约束。
Reserved:系统保留。
Transmit:返回实际发送成功的帧数量。
mta = VCI_CAN_OBJ()
mta.ID = 0x100
mta.TimeStamp = 0
mta.TimeFlag = 0
mta.SendType = 0
mta.RemoteFlag = 0
mta.ExternFlag = 0
mta.DataLen = 8
mta.Data = (0x00, 0x01, 0x02, 0x03,0x04,0x05,0x06,0x07)
transmit = canDLL.Transmit(self.nDeviceType, self.nDeviceInd, self.nCANInd, byref(mta), 1)
Transmit(DWORD DevType, DWORD DevIndex, DWORD CANIndex,P_CAN_OBJ pSend, ULONG Len);
DevType:设备类型号。
DevIndex:设备索引号,比如当只有一个设备时,索引号为0,有两个时可以为0或1。
CANIndex:第几路CAN。
pSend:要发送的数据帧数组的首指针。
Len:要发送的数据帧数组的长度。
返回值:返回实际发送的帧数。
Receive:此函数从指定的设备CAN通道的缓冲区里读取数据。
dto = VCI_CAN_OBJ()
dto.ID = 0x101
dto.TimeStamp = 0
dto.TimeFlag = 0
dto.SendType = 0
dto.RemoteFlag = 0
dto.ExternFlag = 0
dto.DataLen = 8
dto.Data = (0,0,0,0,0,0,0,0)
receive = canDLL.Receive(self.nDeviceType, self.nDeviceInd, self.nCANInd, byref(dto), 1,10)
byref(dto):将接受到的帧信息存放在结构体dto中
1:表示接受的数据帧长度
10:等待超时时间,以毫秒为单位。
1、
receive = canDLL.Receive(self.nDeviceType, self.nDeviceInd, self.nCANInd,byref(dto), 100,400)
将接受到的数据帧长度改为100时,当CAN总线上持续有CAN报文传输时,数组将会溢出,上位机直接卡退。