Python+周立功can卡+can收发

(20) 2024-05-01 15:01:01

周立功官网下载函数库和例程

1、下载函数库
Python+周立功can卡+can收发 (https://mushiming.com/)  第1张
点击下载上面那个(新一点,支持的型号也更多)
下载解压后,把zlgcan.dll复制到python工程的目录下,和自己的代码文件同级就行了
2、下载例程
找到zlgcan.py文件,里面包括了can操作的基本函数

主要的函数

用pycharm打开zlgcan.py,浅浅阅读之后,发现重要的部分基本在ZCAN类里
Python+周立功can卡+can收发 (https://mushiming.com/)  第2张
可以看到can设备的开启、can通信的开启,还有发送接收数据都在这里
ZCAN的初始化里,调用了ddl库(也就是第一步下载的那个),这里建议把路径改为相对,不然可能报找不到文件的错

class ZCAN(object):
    def __init__(self):
        if platform.system() == "Windows":
            self.__dll = windll.LoadLibrary("E:/ITIProjects/VibrationMonitoring/VMProject/zlgcan.dll")
        else:
            print("No support now!")
        if self.__dll == None:
            print("DLL couldn't be loaded!")

实践

1、can参数初始化
官方例程提供了一个can_start函数,在这里面可以修改can的相关配置

def can_start(zcanlib, device_handle, chn):
    ip = zcanlib.GetIProperty(device_handle)
    ret = zcanlib.SetValue(ip, str(chn) + "/clock", "60000000")  #时钟
    if ret != ZCAN_STATUS_OK:
        print("Set CH%d CANFD clock failed!" %(chn))
    ret = zcanlib.SetValue(ip, str(chn) + "/canfd_standard", "0")  #协议?这个置0/1都行
    if ret != ZCAN_STATUS_OK:
        print("Set CH%d CANFD standard failed!" %(chn))
    ret = zcanlib.SetValue(ip, str(chn) + "/initenal_resistance", "1")  #这个我猜是终端电阻
    if ret != ZCAN_STATUS_OK:
        print("Open CH%d resistance failed!" %(chn))
    ret = zcanlib.SetValue(ip, str(chn) + "/canfd_abit_baud_rate", "500000")  # 应该是通道0波特率
    if ret != ZCAN_STATUS_OK:
        print("Set CH%d CANFD canfd_abit_baud_rate failed!" %(chn))
    ret = zcanlib.SetValue(ip, str(chn) + "/canfd_dbit_baud_rate", "2000000")  # 通道1波特率
    if ret != ZCAN_STATUS_OK:
        print("Set CH%d CANFD canfd_dbit_baud_rate failed!" %(chn))
    zcanlib.ReleaseIProperty(ip) 

    chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG()
    chn_init_cfg.can_type = ZCAN_TYPE_CANFD
    #chn_init_cfg.config.canfd.abit_timing = 0x0001975e #1Mbps
    #chn_init_cfg.config.canfd.dbit_timing = 101166 #1Mbps
    chn_init_cfg.config.canfd.mode        = 0
    chn_handle = zcanlib.InitCAN(device_handle, chn, chn_init_cfg)
    if chn_handle is None:
        return None
    zcanlib.StartCAN(chn_handle)  #开启
    return chn_handle

2、打开can设备和通道

zcanlib = ZCAN()  # 创建can实例
handle = zcanlib.OpenDevice(ZCAN_USBCANFD_200U, 0,0)  #打开can设备,这里第一个参数是设备型号,后面2个填0就行
chn_handle = can_start(zcanlib, handle, 0) 

3、can接收

while True:
    rcv_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CAN)  # 接收can信号
    rcv_canfd_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CANFD)  # 接收fdcan信号
    if rcv_num:  # 接收到了can信号
        print("Receive CAN message number:%d" % rcv_num)
        rcv_msg, rcv_num = zcanlib.Receive(chn_handle, rcv_num)
        for i in range(rcv_num):  # 下面的几个参数是can报文中的参数,不多解释
            print("[%d]:ts:%d, id:%d, dlc:%d, eff:%d, rtr:%d, data:%s" %(i, rcv_msg[i].timestamp, 
                  rcv_msg[i].frame.can_id, rcv_msg[i].frame.can_dlc, 
                  rcv_msg[i].frame.eff, rcv_msg[i].frame.rtr,
                  ' '.join(hex(rcv_msg[i].frame.data[j]) for j in range(rcv_msg[i].frame.can_dlc))))  # hex是查看16进制的报文
    elif rcv_canfd_num:  # 接收到了fdcan信号
        print("Receive CANFD message number:%d" % rcv_canfd_num)
        rcv_canfd_msgs, rcv_canfd_num = zcanlib.ReceiveFD(chn_handle, rcv_canfd_num, 1000)
        for i in range(rcv_canfd_num):
            print("[%d]:ts:%d, id:%d, len:%d, eff:%d, rtr:%d, esi:%d, brs: %d, data:%s" %(
                    i, rcv_canfd_msgs[i].timestamp, rcv_canfd_msgs[i].frame.can_id, rcv_canfd_msgs[i].frame.len,
                    rcv_canfd_msgs[i].frame.eff, rcv_canfd_msgs[i].frame.rtr, 
                    rcv_canfd_msgs[i].frame.esi, rcv_canfd_msgs[i].frame.brs,
                    ' '.join(hex(rcv_canfd_msgs[i].frame.data[j]) for j in range(rcv_canfd_msgs[i].frame.len))))
    else:
        print("no msg")
        time.sleep(0.1)

Python+周立功can卡+can收发 (https://mushiming.com/)  第3张

接收函数就是这么个流程,按需修改即可

4、can发送

transmit_num = 10  # 发送can报文数量
msgs = (ZCAN_Transmit_Data * transmit_num)()  # ZCAN_Transmit_Data 是定义在前面的一个can报文结构体
for i in range(transmit_num):
    msgs[i].transmit_type = 0 #Send Self # 这个不知道是啥,其他参数都很简单
    msgs[i].frame.eff     = 0 #extern frame
    msgs[i].frame.rtr     = 0 #remote frame
    msgs[i].frame.can_id  = i
    msgs[i].frame.can_dlc = 8
    for j in range(msgs[i].frame.can_dlc):
        msgs[i].frame.data[j] = j  # 这里定义数据内容
ret = zcanlib.Transmit(chn_handle, msgs, transmit_num)  # 发送出去
print("Tranmit Num: %d." % ret)
THE END

发表回复