使用python来调用CAN通讯的DLL实现方法


Posted in Python onJuly 03, 2019

由于工作上的需要,经常要与USBCAN打交道,但厂家一般不会提供PYTHON的例子,于是自己摸索地写一个例子出来,以便在工作上随时可以使用PYTHON来测试CAN的功能。这里的例子是使用珠海创芯科技有限公司的USBCAN接口卡,他们提供一个ControlCAN.dll,也提供了一个.h文件,如下:

#ifndef CONTROLCAN_H
#define CONTROLCAN_H
 
////文件版本:v2.00 20150920
//#include <cvidef.h>	//使用CVI平台开发,请使用该语句。
 
//接口卡类型定义
 
#define VCI_USBCAN1		3
#define VCI_USBCAN2		4
#define VCI_USBCAN2A		4
 
#define VCI_USBCAN_E_U 		20
#define VCI_USBCAN_2E_U 	21
 
 
 
//函数调用返回状态值
#define	STATUS_OK					1
#define STATUS_ERR					0
	
/*------------------------------------------------兼容ZLG的函数及数据类型------------------------------------------------*/
//1.ZLGCAN系列接口卡信息的数据类型。
typedef struct _VCI_BOARD_INFO{
		unsigned short	hw_Version;
		unsigned short	fw_Version;
		unsigned short	dr_Version;
		unsigned short	in_Version;
		unsigned short	irq_Num;
		unsigned char	can_Num;
		char	str_Serial_Num[20];
		char	str_hw_Type[40];
		unsigned short	Reserved[4];
} VCI_BOARD_INFO,*PVCI_BOARD_INFO; 
 
//2.定义CAN信息帧的数据类型。
typedef struct _VCI_CAN_OBJ{
	unsigned int	ID;
	unsigned int	TimeStamp;
	unsigned char	TimeFlag;
	unsigned char	SendType;
	unsigned char	RemoteFlag;//是否是远程帧
	unsigned char	ExternFlag;//是否是扩展帧
	unsigned char	DataLen;
	unsigned char	Data[8];
	unsigned char	Reserved[3];
}VCI_CAN_OBJ,*PVCI_CAN_OBJ;
 
//3.定义初始化CAN的数据类型
typedef struct _VCI_INIT_CONFIG{
	unsigned long	AccCode;
	unsigned long	AccMask;
	unsigned long	Reserved;
	unsigned char	Filter;
	unsigned char	Timing0;	
	unsigned char	Timing1;	
	unsigned char	Mode;
}VCI_INIT_CONFIG,*PVCI_INIT_CONFIG;
 
///////// new add struct for filter /////////
typedef struct _VCI_FILTER_RECORD{
	unsigned long	ExtFrame;	//是否为扩展帧
	unsigned long	Start;
	unsigned long	End;
}VCI_FILTER_RECORD,*PVCI_FILTER_RECORD;
 
#define EXTERNC		extern "C"
 
EXTERNC unsigned long __stdcall VCI_OpenDevice(unsigned long DeviceType,unsigned long DeviceInd,unsigned long Reserved);
EXTERNC unsigned long __stdcall VCI_CloseDevice(unsigned long DeviceType,unsigned long DeviceInd);
EXTERNC unsigned long __stdcall VCI_InitCAN(unsigned long DeviceType, unsigned long DeviceInd, unsigned long CANInd, PVCI_INIT_CONFIG pInitConfig);
 
EXTERNC unsigned long __stdcall VCI_ReadBoardInfo(unsigned long DeviceType,unsigned long DeviceInd,PVCI_BOARD_INFO pInfo);
 
EXTERNC unsigned long __stdcall VCI_SetReference(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,unsigned long RefType,void* pData);
 
EXTERNC unsigned long __stdcall VCI_GetReceiveNum(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd);
EXTERNC unsigned long __stdcall VCI_ClearBuffer(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd);
 
EXTERNC unsigned long __stdcall VCI_StartCAN(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd);
EXTERNC unsigned long __stdcall VCI_ResetCAN(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd);
 
EXTERNC unsigned long __stdcall VCI_Transmit(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,PVCI_CAN_OBJ pSend,unsigned long Len);
EXTERNC unsigned long __stdcall VCI_Receive(unsigned long DeviceType,unsigned long DeviceInd,unsigned long CANInd,PVCI_CAN_OBJ pReceive,unsigned long Len,int WaitTime);
 
 
/*------------------------------------------------其他补充函数及数据结构描述------------------------------------------------*/
 
//USB-CAN总线适配器板卡信息的数据类型1,该类型为VCI_FindUsbDevice函数的返回参数。
typedef struct _VCI_BOARD_INFO1{
	unsigned long	hw_Version;
	unsigned long	fw_Version;
	unsigned long	dr_Version;
	unsigned long	in_Version;
	unsigned long	irq_Num;
	unsigned char	can_Num;
	unsigned char	Reserved;
	char	str_Serial_Num[8];
	char	str_hw_Type[16];
	char	str_Usb_Serial[4][4];
} VCI_BOARD_INFO1,*PVCI_BOARD_INFO1;
 
//USB-CAN总线适配器板卡信息的数据类型2,该类型为VCI_FindUsbDevice函数的返回参数。为扩展更多的设备
typedef struct _VCI_BOARD_INFO2{
	unsigned long	hw_Version;
	unsigned long	fw_Version;
	unsigned long	dr_Version;
	unsigned long	in_Version;
	unsigned long	irq_Num;
	unsigned char	can_Num;
	unsigned char	Reserved;
	char	str_Serial_Num[8];
	char	str_hw_Type[16];
	char	str_Usb_Serial[10][4];
} VCI_BOARD_INFO2,*PVCI_BOARD_INFO2;
 
 
#define EXTERNC		extern "C"
 
EXTERNC unsigned long __stdcall VCI_GetReference2(unsigned long DevType,unsigned long DevIndex,unsigned long CANIndex,unsigned long Reserved,unsigned char *pData);
EXTERNC unsigned long __stdcall VCI_SetReference2(unsigned long DevType,unsigned long DevIndex,unsigned long CANIndex,unsigned long RefType,unsigned char *pData);
 
 
EXTERNC unsigned long __stdcall VCI_ConnectDevice(unsigned long DevType,unsigned long DevIndex);
EXTERNC unsigned long __stdcall VCI_UsbDeviceReset(unsigned long DevType,unsigned long DevIndex,unsigned long Reserved);
EXTERNC unsigned long __stdcall VCI_FindUsbDevice(PVCI_BOARD_INFO1 pInfo);
EXTERNC unsigned long __stdcall VCI_FindUsbDevice2(PVCI_BOARD_INFO2 pInfo);
 
 
 
#endif

要调用这些函数才可以完成工作,下面就来创建一个例子,从CAN的通道0向通道1来发送一帧CAN数据,例子代码如下:

#python3.6 32位
#https://blog.csdn.net/caimouse/article/details/51749579
#开发人员:蔡军生(QQ:9073204) 深圳 2018-3-25
#
from ctypes import *
 
VCI_USBCAN2A = 4
STATUS_OK = 1
class VCI_INIT_CONFIG(Structure): 
  _fields_ = [("AccCode", c_ulong),
        ("AccMask", c_ulong),
        ("Reserved", c_ulong),
        ("Filter", c_ubyte),
        ("Timing0", c_ubyte),
        ("Timing1", c_ubyte),
        ("Mode", c_ubyte)
        ] 
class VCI_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)
        ] 
 
CanDLLName = 'ControlCAN.dll' #DLL是32位的,必须使用32位的PYTHON
canDLL = windll.LoadLibrary(CanDLLName)
print(CanDLLName)
 
ret = canDLL.VCI_OpenDevice(VCI_USBCAN2A, 0, 0)
print(ret)
if ret != STATUS_OK:
  print('调用 VCI_OpenDevice出错\r\n')
 
#初始0通道
vci_initconfig = VCI_INIT_CONFIG(0x80000008, 0xFFFFFFFF, 0,
                 2, 0x00, 0x1C, 0)
ret = canDLL.VCI_InitCAN(VCI_USBCAN2A, 0, 0, byref(vci_initconfig))
if ret != STATUS_OK:
  print('调用 VCI_InitCAN出错\r\n')
 
ret = canDLL.VCI_StartCAN(VCI_USBCAN2A, 0, 0)
if ret != STATUS_OK:
  print('调用 VCI_StartCAN出错\r\n')
 
#初始1通道
ret = canDLL.VCI_InitCAN(VCI_USBCAN2A, 0, 1, byref(vci_initconfig))
if ret != STATUS_OK:
  print('调用 VCI_InitCAN 1 出错\r\n')
 
ret = canDLL.VCI_StartCAN(VCI_USBCAN2A, 0, 1)
if ret != STATUS_OK:
  print('调用 VCI_StartCAN 1 出错\r\n')
 
#通道0发送数据
ubyte_array = c_ubyte*8
a = ubyte_array(1,2,3,4, 5, 6, 7, 64)
ubyte_3array = c_ubyte*3
b = ubyte_3array(0, 0 , 0)
vci_can_obj = VCI_CAN_OBJ(0x0, 0, 0, 1, 0, 0, 8, a, b)
 
ret = canDLL.VCI_Transmit(VCI_USBCAN2A, 0, 0, byref(vci_can_obj), 1)
if ret != STATUS_OK:
  print('调用 VCI_Transmit 出错\r\n')
 
#通道1接收数据
a = ubyte_array(0, 0, 0, 0, 0, 0, 0, 0)
vci_can_obj = VCI_CAN_OBJ(0x0, 0, 0, 1, 0, 0, 8, a, b)
ret = canDLL.VCI_Receive(VCI_USBCAN2A, 0, 1, byref(vci_can_obj), 1, 0)
print(ret)
while ret <= 0:
  print('调用 VCI_Receive 出错\r\n')
  ret = canDLL.VCI_Receive(VCI_USBCAN2A, 0, 1, byref(vci_can_obj), 1, 0)
if ret > 0:
  print(vci_can_obj.DataLen)
  print(list(vci_can_obj.Data))
 
#关闭
canDLL.VCI_CloseDevice(VCI_USBCAN2A, 0)

运行结果输出如下:

ControlCAN.dll
1
1
8

[1, 2, 3, 4, 5, 6, 7, 64]

可以看到从通道1里收通道0发过来的数据,达到这个程序的目的。

以上这篇使用python来调用CAN通讯的DLL实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
tornado捕获和处理404错误的方法
Feb 26 Python
python中使用正则表达式的连接符示例代码
Oct 10 Python
Python os.rename() 重命名目录和文件的示例
Oct 25 Python
Python之两种模式的生产者消费者模型详解
Oct 26 Python
Python Series从0开始索引的方法
Nov 06 Python
python基础梳理(一)(推荐)
Apr 06 Python
Python学习笔记之抓取某只基金历史净值数据实战案例
Jun 03 Python
Django自带日志 settings.py文件配置方法
Aug 30 Python
wxPython实现分隔窗口
Nov 19 Python
python+tifffile之tiff文件读写方式
Jan 13 Python
信号生成及DFT的python实现方式
Feb 25 Python
pycharm配置QtDesigner的超详细方法
Jan 25 Python
opencv python 图像轮廓/检测轮廓/绘制轮廓的方法
Jul 03 #Python
在cmd中查看python的安装路径方法
Jul 03 #Python
python动态进度条的实现代码
Jul 03 #Python
OpenCV 轮廓检测的实现方法
Jul 03 #Python
python实现文本进度条 程序进度条 加载进度条 单行刷新功能
Jul 03 #Python
Python Pandas数据结构简单介绍
Jul 03 #Python
如何通过雪花算法用Python实现一个简单的发号器
Jul 03 #Python
You might like
php 时间计算问题小结
2009/01/04 PHP
php 遍历数据表数据并列表横向排列的代码
2009/09/05 PHP
php实现字符串首字母转换成大写的方法
2015/03/17 PHP
php超快高效率统计大文件行数
2015/07/05 PHP
php基于双向循环队列实现历史记录的前进后退等功能
2015/08/08 PHP
PHP执行shell脚本运行程序不产生core文件的方法
2016/12/28 PHP
PHP Primary script unknown 解决方法总结
2019/08/22 PHP
jquery 新手学习常见问题解决方法
2010/04/18 Javascript
jQuery示例收集
2010/11/05 Javascript
jQuery代码优化之基本事件
2011/11/01 Javascript
Jquery创建层显示标题和内容且随鼠标移动而移动
2014/01/26 Javascript
js和jquery中循环的退出和继续下一个循环
2014/09/03 Javascript
JavaScript插件化开发教程 (二)
2015/01/27 Javascript
jQuery经过一段时间自动隐藏指定元素的方法
2015/03/17 Javascript
jQuery实现在最后一个元素之前插入新元素的方法
2015/07/18 Javascript
基于JS实现的倒计时程序实例
2015/07/24 Javascript
jquery ztree实现树的搜索功能
2016/02/25 Javascript
JS处理数据四舍五入(tofixed与round的区别详解)
2017/10/26 Javascript
js 图片转base64的方式(两种)
2018/04/24 Javascript
微信小程序当前时间时段选择器插件使用方法详解
2018/12/28 Javascript
JavaScript组合设计模式--改进引入案例分析
2020/05/23 Javascript
使用Python设置tmpfs来加速项目的教程
2015/04/17 Python
Django 跨域请求处理的示例代码
2018/05/02 Python
python使用suds调用webservice接口的方法
2019/01/03 Python
pytorch打印网络结构的实例
2019/08/19 Python
Python如何转换字符串大小写
2020/06/04 Python
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
法国在线购买汽车轮胎网站:123pneus.fr
2019/02/25 全球购物
俄罗斯奢侈品牌衣服、鞋子和配饰的在线商店:INTERMODA
2020/07/17 全球购物
总裁办公室主任职责
2014/01/02 职场文书
致长跑运动员广播稿
2014/01/31 职场文书
初中英语课后反思
2014/04/25 职场文书
反腐倡廉学习心得体会范文
2015/08/15 职场文书
apache基于端口创建虚拟主机的示例
2021/04/24 Servers
python中的mysql数据库LIKE操作符详解
2021/07/01 MySQL
高通2023 年将发布高性能PC处理器
2022/04/29 数码科技