PyQt5+周立功 CAN上位机制作

PyQt5+周立功 CAN上位机制作

python 环境安装 PyQt5

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)]

对ControlCAN.dll进行适配python的封装

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、软件升级的界面

PyQt5+周立功 CAN上位机制作_第1张图片

你可能感兴趣的:(笔记,python,can)