使用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 相关文章推荐
python读文件逐行处理的示例代码分享
Dec 27 Python
python中使用smtplib和email模块发送邮件实例
Apr 22 Python
Python警察与小偷的实现之一客户端与服务端通信实例
Oct 09 Python
centos 下面安装python2.7 +pip +mysqld
Nov 18 Python
PyQt5利用QPainter绘制各种图形的实例
Oct 19 Python
python退出命令是什么?详解python退出方法
Dec 10 Python
Python图像处理之图像的读取、显示与保存操作【测试可用】
Jan 04 Python
python实现在函数中修改变量值的方法
Jul 16 Python
Python编程快速上手——正则表达式查找功能案例分析
Feb 28 Python
Python3自定义json逐层解析器代码
May 11 Python
Python数据相关系数矩阵和热力图轻松实现教程
Jun 16 Python
python使用matplotlib绘制折线图的示例代码
Sep 22 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
古巴咖啡 Cubita琥爵咖啡 独特的加勒比海风味咖啡
2021/03/06 新手入门
php将mysql数据库整库导出生成sql文件的具体实现
2014/01/08 PHP
PHP实现字符串的全排列详解
2019/04/24 PHP
javascript Select标记中options操作方法集合
2008/10/22 Javascript
jquery $.ajax相关用法分享
2012/03/16 Javascript
javascript针对DOM的应用分析(三)
2012/04/15 Javascript
jquery创建一个ajax关键词数据搜索实现思路
2013/02/26 Javascript
jQuery实现鼠标经过图片预览大图效果
2014/04/10 Javascript
jquery小火箭返回顶部代码分享
2015/08/19 Javascript
利用HTML5的画布Canvas实现刮刮卡效果
2015/09/06 Javascript
JS中使用apply方法通过不同数量的参数调用函数的方法
2016/05/31 Javascript
深入剖析JavaScript面向对象编程
2016/07/12 Javascript
详解使用Visual Studio Code对Node.js进行断点调试
2017/09/14 Javascript
vue.js提交按钮时进行简单的if判断表达式详解
2018/08/08 Javascript
卸载vue2.0并升级vue_cli3.0的实例讲解
2020/02/16 Javascript
[01:33]一分钟玩转DOTA2第三弹:DOTA2&DotA快捷操作大对比
2014/06/04 DOTA
[04:05]TI9战队采访 - Natus Vincere
2019/08/22 DOTA
hmac模块生成加入了密钥的消息摘要详解
2018/01/11 Python
Python实现带参数与不带参数的多重继承示例
2018/01/30 Python
Django 路由控制的实现代码
2018/11/08 Python
PyTorch基本数据类型(一)
2019/05/22 Python
python实现飞机大战游戏(pygame版)
2020/10/26 Python
利用 Python ElementTree 生成 xml的实例
2020/03/06 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
2020/04/08 Python
纯CSS3制作页面切换效果的实例代码
2019/05/30 HTML / CSS
印度尼西亚最大的电商平台:Tokopedia(印尼版淘宝)
2017/12/02 全球购物
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
预备党员入党思想汇报
2014/01/04 职场文书
大学生水果店创业计划书
2014/01/28 职场文书
《吃水不忘挖井人》教学反思
2014/04/15 职场文书
员工三分钟演讲稿
2014/08/19 职场文书
2014年教学工作总结
2014/11/13 职场文书
留学推荐信中文范文
2015/03/26 职场文书
2015年乡镇工作总结范文
2015/04/22 职场文书
php 防护xss,PHP的防御XSS注入的终极解决方案
2021/04/01 PHP
详解JavaScript中Arguments对象用途
2021/08/30 Javascript