pip install PyQt5
PyQt5-tools
USB接口CAN卡-广州致远电子有限公司
ZLG官网给的python例程是基于库文件 zlgcan.dll + tkinter 的方式,这里使用 ControlCAN.dll + PyQt5的方式,所以只下载最新的开发接口库,而没去下载他们的上位机例程序(当然也可以参考)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-19A7xpvT-1629971500710)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a939c9d8-ce6b-458a-b6d0-e555629346fe/Untitled.png)]
解压从ZLG官网下载下来的压缩包,取出 ControlCAN.dll + kerneldlls文件夹,将其放入我们自己的工程 —-注意其需要在同一目录等级下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LN2WKJIP-1629971500712)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/598e45ab-99f6-4610-8914-2c272d950c51/Untitled.png)]
from ctypes import *
import platform
import os
INVALID_DEVICE_HANDLE = 0
INVALID_CHANNEL_HANDLE = 0
#os.add_dll_directory(r"C:\Users\user\Desktop\ZLG\zlgcan_demo\zlgcan_python")
'''
Device Type
'''
#设备类型选择--根据广州致远电子有限公司 CAN测试软件和接口函数使用手册
ZCAN_PCI5121 = c_uint(1)
ZCAN_PCI98101 = c_uint(2)
ZCAN_USBCAN1 = c_uint(3)
ZCAN_USBCAN2 = c_uint(4)
'''
Interface return status
'''
ZCAN_STATUS_ERR = 0
ZCAN_STATUS_OK = 1
ZCAN_STATUS_ONLINE = 2
ZCAN_STATUS_OFFLINE = 3
ZCAN_STATUS_UNSUPPORTED = 4
'''
Device information
'''
'''
board info
'''
class ZCAN_BOARD_INFO(Structure):
_fields_ = [("hw_Version", c_ushort),
("fw_Version", c_ushort),
("dr_Version", c_ushort),
("in_Version", c_ushort),
("irq_Num", c_ushort),
("can_Num", c_ubyte),
("str_Serial_Num", c_ubyte * 20),
("str_hw_Type", c_ubyte * 40),
("reserved", c_ushort * 4)]
def __str__(self):
return "Hardware Version:%s\nFirmware Version:%s\nDriver Interface:%s\nInterface Interface:%s\nInterrupt Number:%d\nCAN Number:%d\nSerial:%s\nHardware Type:%s\n" % ( \
self.hw_version, self.fw_version, self.dr_version, self.in_version, self.irq_num, self.can_num, self.serial,
self.hw_type)
def _version(self, version):
return ("V%02x.%02x" if version // 0xFF >= 9 else "V%d.%02x") % (version // 0xFF, version & 0xFF)
@property
def hw_version(self):
return self._version(self.hw_Version)
@property
def fw_version(self):
return self._version(self.fw_Version)
@property
def dr_version(self):
return self._version(self.dr_Version)
@property
def in_version(self):
return self._version(self.in_Version)
@property
def irq_num(self):
return self.irq_Num
@property
def can_num(self):
return self.can_Num
@property
def serial(self):
serial = ''
for c in self.str_Serial_Num:
if c > 0:
serial += chr(c)
else:
break
return serial
@property
def hw_type(self):
hw_type = ''
for c in self.str_hw_Type:
if c > 0:
hw_type += chr(c)
else:
break
return hw_type
'''
VCI_INIT_CONFIG
'''
class ZCAN_CHANNEL_CAN_INIT_CONFIG(Structure):
_fields_ = [("acc_code", c_uint),
("acc_mask", c_uint),
("reserved", c_uint),
("filter", c_ubyte),
("timing0", c_ubyte),
("timing1", c_ubyte),
("mode", c_ubyte)]
'''
VCI_ERR_INFO
@1 错误码
@2 当产生的错误中有消极错误时表示为消极错误的错误标识数据
@3 当产生的错误中有仲裁丢失错误时表示为仲裁丢失错误的错误标识数据。
'''
class ZCAN_CHANNEL_ERR_INFO(Structure):
_fields_ = [("error_code", c_uint),
("passive_ErrData", c_ubyte * 3),
("arLost_ErrData", c_ubyte)]
'''
VCI_CAN_STATUS
'''
class ZCAN_CHANNEL_STATUS(Structure):
_fields_ = [("errInterrupt", c_ubyte),
("regMode", c_ubyte),
("regStatus", c_ubyte),
("regALCapture", c_ubyte),
("regECCapture", c_ubyte),
("regEWLimit", c_ubyte),
("regRECounter", c_ubyte),
("regTECounter", c_ubyte),
("Reserved", c_ubyte)]
'''
VCI_CAN_OBJ
'''
class ZCAN_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)]
'''
CAN CLASS
'''
class ZCAN(object):
def __init__(self):
if platform.system() == "Windows":
self.__dll = windll.LoadLibrary("ControlCAN.dll")
else:
print("No support now")
if self.__dll is None:
print("load ControlCAN.dll err")
def OpenDevice(self, device_type, device_index, reserved):
try:
ret = self.__dll.VCI_OpenDevice(device_type, device_index, reserved)
return ret
except:
print("except on opendevice")
raise
def CloseDevice(self, device_type, device_index):
try:
return self.__dll.VCI_CloseDevice(device_type, device_index)
except:
print("except on closedevice")
raise
def InitCAN(self, device_type, device_index, can_index,init_config):
try:
return self.__dll.VCI_InitCAN(device_type, device_index, can_index, pointer(init_config))
except:
print("except on InitCAN")
raise
def GetBoardinfo(self,device_type, device_index):
try:
board_info = ZCAN_BOARD_INFO()
ret = self.__dll.VCI_ReadBoardInfo(device_type, device_index, byref(board_info))
return board_info if ret == ZCAN_STATUS_OK else None
except:
print("read boardinfo err")
raise
def ReadErrInfo(self, device_type, device_index, can_index):
try:
errInfo = ZCAN_CHANNEL_ERR_INFO()
ret = self.__dll.VCI_ReadErrInfo(device_type, device_index, can_index, byref(errInfo))
return errInfo if ret == ZCAN_STATUS_OK else None
except:
print("except on ReadErrInfo")
raise
def ReadCanStatus(self,device_type, device_index, can_index):
try:
errInfo = ZCAN_CHANNEL_STATUS()
ret = self.__dll.VCI_ReadCANStatus(device_type, device_index, can_index, byref(errInfo))
return errInfo if ret == ZCAN_STATUS_OK else None
except:
print("except on ReadCanStatus")
raise
def StartCAN(self, device_type, device_index, can_index):
try:
return self.__dll.VCI_StartCAN(device_type, device_index, can_index)
except:
print("except on StartCAN")
raise
def ResetCAN(self, device_type, device_index, can_index):
try:
return self.__dll.VCI_ResetCAN(device_type, device_index, can_index)
except:
print("except on StartCAN")
raise
def GetReceiveNum(self,device_type, device_index, can_index):
try:
return self.__dll.VCI_GetReceiveNum(device_type, device_index, can_index)
except:
print("except on GetReceiveNum")
raise
def ClearBuffer(self,device_type, device_index, can_index):
try:
return self.__dll.VCI_ClearBuffer(device_type, device_index, can_index)
except:
print("except on ClearBuffer")
raise
def Transmit(self,device_type, device_index, can_index, std_msg, lenth):
try:
return self.__dll.VCI_Transmit(device_type, device_index, can_index, byref(std_msg), lenth)
except:
print("except on Transmit")
raise
def Recvive(self,device_type, device_index, can_index,rcv_num, wait_time = c_int(-1)):
try:
print("rcv_num =",rcv_num)
recv_can_msgs = (ZCAN_CAN_OBJ * rcv_num)()
ret = self.__dll.VCI_Receive(device_type, device_index, can_index, byref(recv_can_msgs), rcv_num,wait_time)
return recv_can_msgs,ret
except:
print("except on Transmit")
raise
#测试代码
if __name__ == "__main__":
zcanlib = ZCAN()
ret = zcanlib.OpenDevice(ZCAN_USBCAN2, 0, 0)
if ret != ZCAN_STATUS_OK:
print("open can device err")
exit(0)
info = zcanlib.GetBoardinfo(ZCAN_USBCAN2, 0)
print("board infomation: %s" %(info))
iniconfig = ZCAN_CHANNEL_CAN_INIT_CONFIG()
iniconfig.acc_code = 0x00000000
iniconfig.acc_mask = 0xffffffff
iniconfig.filter = 1
iniconfig.timing0 = 0x00
iniconfig.timing1 = 0x1C
iniconfig.mode = 0
ret = zcanlib.InitCAN(ZCAN_USBCAN2, 0, 0,iniconfig)
if ret != ZCAN_STATUS_OK:
print("init can device err")
exit(0)
ret = zcanlib.StartCAN(ZCAN_USBCAN2, 0, 0)
if ret != ZCAN_STATUS_OK:
print("start can device err")
exit(0)
#send msg
trams_nums = 10
msgs = (ZCAN_CAN_OBJ * trams_nums)()
for i in range(trams_nums):
msgs[i].ID = 0x123
msgs[i].SendType = 1
msgs[i].RemoteFlag = 0
msgs[i].ExternFlag = 0
msgs[i].DataLen = 8
for j in range(msgs[i].DataLen):
msgs[i].Data[j] = j
ret = zcanlib.Transmit(ZCAN_USBCAN2, 0, 0, msgs, trams_nums)
print("ret = %d" % ret)
sum_recv = 0
while True:
try:
recv_num = zcanlib.GetReceiveNum(ZCAN_USBCAN2, 0, 0)
if recv_num:
print("recv_num = %d" % recv_num)
recv_msg, num = zcanlib.Recvive(ZCAN_USBCAN2, 0, 0, recv_num)
sum_recv += num
print("num = ", sum_recv)
if num>0 and recv_msg is not None:
print("num = %d", num)
for i in range(num):
print("[%d,%d]:ID:%08x, DLC:%d data:%s" %(i, recv_msg[i].TimeStamp, recv_msg[i].ID, \
recv_msg[i].DataLen, \
''.join(str(recv_msg[i].Data[j]) + ' ' for j in range(recv_msg[i].DataLen))))
except:
print("main err num ")
raise
zcanlib.ClearBuffer(ZCAN_USBCAN2, 0, 0)
zcanlib.CloseDevice(ZCAN_USBCAN2, 0)
以上仅是简单的对 .dll做了封装,后面有时间会把后续补上
初步设想:
使用designer 设计三个界面,分别为1、通用的CAN调试界面;2、适配具体项目的界面;3、软件升级的界面