公司买了最便宜的那种USBCAN,一般使用Labview可以进行开发,但是面向对象的属性较差,于是想使用python调用dll文件的方式进行开发。
需要参考设备自带的开发手册文件,可以去他们公司公众号下载
和周立功的开发方式差不多,所以代码可参考
https://blog.csdn.net/caimouse/article/details/79692118
https://blog.csdn.net/yy123xiang/article/details/79655661
下面代码实现一个基本的单通道收发功能,可以用另一个设备进行收发测试。
from ctypes import *
import time
dll = windll.LoadLibrary('./ECanVci64.dll') # 调用dll文件
nDeviceType = 4 # 设备类型USBCAN-2E-U
nDeviceInd = 0 # 索引号0,代表设备个数
nReserved = 0 # 无意义参数
# nCANInd = 1 # can通道号
# 定义一个python的'结构体',使用ctypes继承Structure,内容是初始化需要的参数,依据产品手册
class VciInitConfig(Structure):
_fields_ = [("AccCode", c_ulong), # 验收码,后面是数据类型
("AccMask", c_ulong), # 屏蔽码
("Reserved", c_ulong), # 保留
("Filter", c_ubyte), # 滤波使能。0=不使能,1=使能使能时,/
# 请参照SJA1000验收滤波器设置验收码和屏蔽码。
("Timing0", c_ubyte), # 波特率定时器0(BTR0)
("Timing1", c_ubyte), # 波特率定时器1(BTR1)
("Mode", c_ubyte)] # 模式。=0为正常模式,=1为只听模式, =2为自发自收模式
# 定义发送报文的结构体
class VciCanObj(Structure):
_fields_ = [("ID", c_uint), # 报文帧ID'''
("TimeStamp", c_uint), # 接收到信息帧时的时间标识
("TimeFlag", c_ubyte), # 是否使用时间标识, 为1时TimeStamp有效
("SendType", c_ubyte), # 发送帧类型。=0时为正常发送,=1时为单次发送(不自动重发),/
# =2时为自发自收(用于测试CAN卡是否损坏) , =3时为单次自发自收(只发送一次, 用于自测试),/
# 只在此帧为发送帧时有意义。
("RemoteFlag", c_ubyte), # 是否是远程帧。=0时为数据帧,=1时为远程帧。
("ExternFlag", c_ubyte), # 是否是扩展帧。=0时为标准帧(11位帧ID),=1时为扩展帧(29位帧ID)。
("DataLen", c_ubyte), # 数据长度DLC(<=8), 即Data的长度
("Data", c_ubyte * 8), # CAN报文的数据。 空间受DataLen的约束。
("Reserved", c_ubyte * 3)] # 系统保留
# 定义一个用于初始化的实例对象vic
vic = VciInitConfig()
vic.AccCode = 0x00000000
vic.AccMask = 0xffffffff
vic.reserved = 0
vic.Filter = 0
vic.Timing0 = 0x00 # 500Kbps
vic.Timing1 = 0x1C # 500Kbps
vic.Mode = 0
# 定义报文实例对象,用于发送
vco = VciCanObj()
vco.ID = 0x00000055 # 帧的ID
vco.SendType = 1 # 发送帧类型,0是正常发送,1为单次发送,这里要选1!要不发不去!
vco.RemoteFlag = 0
vco.ExternFlag = 0
vco.DataLen = 8
vco.Data = (1, 2, 3, 4, 5, 6, 7, 0)
vco.Reserved = (0, 0, 0)
# 也可以用下面的定义方式,其中报文可以用0x的表达选择是16进制还是10进制
'''
ubyte_array = c_ubyte * 8
a = ubyte_array(1, 2, 3, 4, 5, 6, 7, 0x64)
ubyte_3array = c_ubyte * 3
b = ubyte_3array(0, 0, 0)
vco = VciCanObj(0x01, 0, 0, 1, 0, 0, 8, a)
'''
# 定义报文实例对象,用于接收
vco2 = VciCanObj()
vco2.ID = 0x00000001 # 帧的ID 后面会变成真实发送的ID
vco2.SendType = 0 # 这里0就可以收到
vco2.RemoteFlag = 0
vco2.ExternFlag = 0
vco2.DataLen = 8
vco2.Data = (0, 0, 0, 0, 0, 0, 0, 0)
'''设备的打开如果是双通道的设备的话,可以再用initcan函数初始化'''
# OpenDevice(设备类型号,设备索引号,参数无意义)
ret = dll.OpenDevice(nDeviceType, nDeviceInd, nReserved)
print("opendevice:", ret)
# InitCAN(设备类型号,设备索引号,第几路CAN,初始化参数initConfig),
ret = dll.InitCAN(nDeviceType, nDeviceInd, 0, byref(vic))
print("initcan0:", ret)
# StartCAN(设备类型号,设备索引号,第几路CAN)
ret = dll.StartCAN(nDeviceType, nDeviceInd, 0)
print("startcan0:", ret)
i = 1
while i:
art = dll.Transmit(nDeviceType, nDeviceInd, 0, byref(vco), 1) # 发送vco
ret = dll.Receive(nDeviceType, nDeviceInd, 0, byref(vco2), 1, 0) # 以vco2的形式接收报文
time.sleep(1) # 设置一个循环发送的时间
if ret > 0:
print(i)
print(list(vco2.Data)) # 打印接收到的报文
i += 1
ret = dll.CloseDevice(nDeviceType, nDeviceInd)
print("closedevice:", ret)