使用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 相关文章推荐
MySQL中表的复制以及大型数据表的备份教程
Nov 25 Python
pyhton列表转换为数组的实例
Apr 04 Python
python中使用zip函数出现错误的原因
Sep 28 Python
python搜索包的路径的实现方法
Jul 19 Python
django foreignkey(外键)的实现
Jul 29 Python
python连接、操作mongodb数据库的方法实例详解
Sep 11 Python
复化梯形求积分实例——用Python进行数值计算
Nov 20 Python
使用pyqt 实现重复打开多个相同界面
Dec 13 Python
Python中实现输入超时及如何通过变量获取变量名
Jan 18 Python
pycharm新建Vue项目的方法步骤(图文)
Mar 04 Python
Python urllib2运行过程原理解析
Jun 04 Python
python 详解turtle画爱心代码
Feb 15 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
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
PHP中PDO基础教程 入门级
2011/09/04 PHP
PHP数组 为文章加关键字连接 文章内容自动加链接
2011/12/29 PHP
php简单生成随机数的方法
2015/07/30 PHP
php smtp实现发送邮件功能
2017/06/22 PHP
Laravel框架中Blade模板的用法示例
2017/08/30 PHP
Laravel 5.5基于内置的Auth模块实现前后台登陆详解
2017/12/21 PHP
PHP实现图片压缩
2020/09/09 PHP
获取JavaScript用户自定义类的类名称的代码
2007/03/08 Javascript
理解Javascript_02_理解undefined和null
2010/10/11 Javascript
jQuery实现类似滑动门切换效果的层切换
2013/09/23 Javascript
XMLHttpRequest处理xml格式的返回数据(示例代码)
2013/11/21 Javascript
jQuery中even选择器的定义和用法
2014/12/23 Javascript
jquery实现的点击翻书效果代码
2015/11/04 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
基于JavaScript FileReader上传图片显示本地链接
2016/05/27 Javascript
利用vue-router实现二级菜单内容转换
2016/11/30 Javascript
easyui简介_动力节点Java学院整理
2017/07/14 Javascript
如何测量vue应用运行时的性能
2019/06/21 Javascript
vue 检测用户上传图片宽高的方法
2020/02/06 Javascript
JS数组转字符串实现方法解析
2020/09/04 Javascript
[01:04:09]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第二场 2月2日
2021/03/11 DOTA
编写简单的Python程序来判断文本的语种
2015/04/07 Python
Python做简单的字符串匹配详解
2017/03/21 Python
深入学习Python中的上下文管理器与else块
2017/08/27 Python
解决tensorflow模型参数保存和加载的问题
2018/07/26 Python
Python+AutoIt实现界面工具开发过程详解
2019/08/07 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
python excel转换csv代码实例
2019/08/26 Python
用C或者C++语言实现SOCKET通信
2015/02/24 面试题
新媒传信软件测试面试题
2013/02/24 面试题
技校学生个人职业生涯规划范文
2014/03/03 职场文书
新闻专业毕业生求职信
2014/08/08 职场文书
财务会计个人原因辞职信
2019/06/21 职场文书
你会写请假条吗?
2019/06/26 职场文书
vue中data里面的数据相互使用方式
2022/06/05 Vue.js