前言
程序猿总少不了尝试体验不一样的工具,在”能跑“但是有冲突的情况下,要么我改,要么还是我改…
今天分享一个python使用zlgcan的方法。
关联文件放置
首先需要将zlgcan中的zlgcan.dll,kerneldlls文件夹以及zlgcan.py转移到自己程序的根目录下,需注意DLL文件位数需要与python位数一致,如python32需要32位的DLL。
通道配置
# 创建对象实例
zcanlib = ZCAN()
# 打开通道OpenDevice(device_type =ZCAN_USBCAN2, device_index=0, reserved=0)
dev_handle = zcanlib.OpenDevice(ZCAN_USBCAN2, 0, 0)
# 检测是否打开成功
if dev_handle == INVALID_DEVICE_HANDLE:
win32api.MessageBox(0, "Open Device failed", "Error")
sys.exit(0)
chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG()
# 设置通道为CAN模式
chn_init_cfg.can_type = ZCAN_TYPE_CAN
chn_init_cfg.config.can.acc_mode = 0
chn_init_cfg.config.can.acc_mask = 0xFFFFFFFF
# 波特率设置,250k,具体参考表1
chn_init_cfg.config.can.timing0 = 1
chn_init_cfg.config.can.timing1 = 28
# 初始化通道InitCAN(device_handle, can_index, byref(init_config))
chn_handle = zcanlib.InitCAN(dev_handle, 0, chn_init_cfg)
if chn_handle is None:
return None
# 将通道连接入总线
zcanlib.StartCAN(chn_handle)
return chn_handle
表1:波特率时序对照表
CAN发送
# Transmit(chn_handle, std_msg, len)
# TransmitFD(chn_handle, fd_msg, len)
# 需要提供通道句柄,发送的信息,长度(发送多组信息的组数)
# 创建CAN发送信息实例
msgs = (ZCAN_Transmit_Data * transmit_num)()
for i in range(transmit_num):
# 发送方式,0=正常发送,1=单次发送,2=自发自收,3=单次自发自收。
msgs[i].transmit_type = 2
msgs[i].frame.eff = 0 # 扩展帧
msgs[i].frame.rtr = 0 # 远程帧
msgs[i].frame.can_id = i # CAN ID
msgs[i].frame.can_dlc = 8 # 长度
# 根据CAN数据长度(dlc)输入数据
for j in range(msgs[i].frame.can_dlc):
msgs[i].frame.data[j] = j
# 发送数据
ret = zcanlib.Transmit(chn_handle, msgs, transmit_num)
CAN接收
# Receive(chn_handle, rcv_num, wait_time)
# ReceiveFD(chn_handle,rcv_num, wait_time)
# 数据接收函数,需提供CAN/FD通道句柄,接收信息数,超时(默认:-1 永不超时)
# 获取CAN接收数
rcv_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CAN)
rcv_canfd_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CANFD)
if rcv_num:
print("Receive CAN message number:%d" % rcv_num)
#
rcv_msg, rcv_num = zcanlib.Receive(chn_handle, rcv_num)
for i in range(rcv_num):
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,
# 根据dlc循环输出数据
''.join(str(rcv_msg[i].frame.data[j]) + ' ' for j in range(rcv_msg[i].frame.can_dlc))
))
输出样式:
Demo
from zlgcan import *
import win32api
def busOn(zcanlib):
dev_handle = self.zcanlib.OpenDevice(ZCAN_USBCAN2, 0, 0)
if dev_handle == INVALID_DEVICE_HANDLE:
win32api.MessageBox(0, "Open Device failed", "Error")
sys.exit(0)
chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG()
chn_init_cfg.can_type = ZCAN_TYPE_CAN
chn_init_cfg.config.can.acc_mode = 0
chn_init_cfg.config.can.acc_mask = 0xFFFFFFFF
chn_init_cfg.config.can.timing0 = 1
chn_init_cfg.config.can.timing1 = 28
chn_handle = self.zcanlib.InitCAN(dev_handle, 0, chn_init_cfg)
if chn_handle is None:
return None
zcanlib.StartCAN(chn_handle)
return chn_handle
if __name__ == "__main__":
zcanlib = ZCAN()
bus = busOn(zcanlib)
# 发送数据
msg = ZCAN_Transmit_Data()
msg.transmit_type = 0
msg.frame.eff = 0 # 1为扩展帧
msg.frame.rtr = 0
msg.frame.can_id = 123
msg.frame.can_dlc = 8
for j in range(8):
msg.frame.data[j] = j
zcanlib.Transmit(bus, msg, 1)
# 接收数据
msgs, r_num = self.zcanlib.Receive(bus, 1)
if r_num:
can_data = ""
for byte in msgs[0].frame.data:
can_data += "{:0>2X} ".format(byte)
# 将报文处理为字符列表,8字节变为16个字符
data_list = list(''.join(can_data.split()))
print(data_list)