1、下载函数库
点击下载上面那个(新一点,支持的型号也更多)
下载解压后,把zlgcan.dll复制到python工程的目录下,和自己的代码文件同级就行了
2、下载例程
找到zlgcan.py文件,里面包括了can操作的基本函数
用pycharm打开zlgcan.py,浅浅阅读之后,发现重要的部分基本在ZCAN类里
可以看到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)
接收函数就是这么个流程,按需修改即可
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)