Qt配置USBCAN通信
周立功为CAN通信提供了动态库:官方提供了很多相关动态库和lib等,如图
,其中kerneldlls里还有很多动态库,还有一个配置文件。其实这么多的文件,如果我们只用到USBCAN2通信,只需要kerneldlls里面的usbcan.dll这个动态库,里面真正封装了用了windows和can模块通过usb通信的函数。然后还需要ControlCAN.h这个头文件,里面有对使用dll函数时一些结构体的声明和定义。对于ControlCAN.dll和ControlCAN.lib实际上是对使用usbcan.dll动态库的引导入口。
对于如何使用Qt加载这些动态库来实现CAN通信,有两种方式,1是显式,2是隐式。
显式:通过代码加载动态库我们需要的函数,把这些函数实际放在自己的工程之中;
隐式:通过在工程中加入动态库入口的路径,使可执行文件在运行时在相应路径找动态库,再使用其函数。
一、显式
1、新建工程,在工程中(和源文件放在一起)添加ControlCAN.h头文件、usbcan.dll动态库。
ControlCAN.h是需要包含在工程中的(右键工程-》添加存在路径-》此时默认勾选好了ControlCAN.h,确认即可);usbcan.dll是需要加载的动态库
2、使用QLibrary加载动态库
QLibrary lib("usbcan.dll");
if(true == lib.load())
qDebug()<<"load ok";
3、声明一个自己的函数,功能与usbcan.dll里的函数的功能想对应
比如,usbcan.dll中有个打开设备的函数,那就自己定义一个打开设备的函数,把usbcan.dll中打开设备函数的功能赋值到自定义函数中--!
头文件中:
typedef DWORD(__stdcall VCI_OpenDevice)(DWORD,DWORD,DWORD);//不知道为什么,反正没有就会出错
typedef DWORD(__stdcall VCI_ResetCAN)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
typedef DWORD(__stdcall VCI_CloseDevice)(DWORD DeviceType,DWORD DeviceInd);
typedef DWORD(__stdcall VCI_InitCAN)(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig);
typedef DWORD(__stdcall VCI_StartCAN)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
typedef ULONG(__stdcall VCI_Transmit)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,ULONG Len);
typedef ULONG(__stdcall VCI_Receive)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,ULONG Len,INT WaitTime/*=-1*/);
typedef ULONG(__stdcall VCI_GetReceiveNum)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
typedef DWORD(__stdcall VCI_ClearBuffer)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
typedef DWORD(__stdcall VCI_ReadErrInfo)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_ERR_INFO pErrInfo);
typedef DWORD(__stdcall VCI_ReadCANStatus)(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_STATUS pCANStatus);
以上函数全是can通信重要的函数,全部为自己定义的,名字随便取都可以。
4、使用上面的函数声明对应的函数对象
头文件中:
VCI_OpenDevice *pOpenDevice;
VCI_ResetCAN *pResetCAN;
VCI_CloseDevice *pCloseDevice;
VCI_InitCAN *pInitCAN;
VCI_StartCAN *pStartCAN;
VCI_Transmit *pTransmitCAN;
VCI_Receive *pReceive;
VCI_GetReceiveNum *pGetReceiveNum;
VCI_ClearBuffer *pClearBuffer;
VCI_ReadErrInfo *pReadErrInfoCAN;
VCI_ReadCANStatus *pVCI_ReadCANStatus;
5、引入usbcan.dll动态库
在源文件中:
QLibrary lib("usbcan.dll");
true == lib.load();
6、将usbcan.dll中的函数功能分解到自定义对应函数中
源文件中:
pOpenDevice = (VCI_OpenDevice *)lib.resolve("VCI_OpenDevice");
pCloseDevice = (VCI_CloseDevice *)lib.resolve("VCI_CloseDevice");
pInitCAN = (VCI_InitCAN *)lib.resolve("VCI_InitCAN");
pStartCAN = (VCI_StartCAN *)lib.resolve("VCI_StartCAN");
pTransmitCAN = (VCI_Transmit *)lib.resolve("VCI_Transmit");
pReceive = (VCI_Receive *)lib.resolve("VCI_Receive");
pGetReceiveNum = (VCI_GetReceiveNum *)lib.resolve("VCI_GetReceiveNum");
pClearBuffer = (VCI_ClearBuffer *)lib.resolve("VCI_ClearBuffer");
pReadErrInfoCAN = (VCI_ReadErrInfo*)lib.resolve("VCI_ReadErrInfo");
7、接下来就可以使用自定义的函数来进行CAN总线编程了
二、隐式
1、把ControlCAN.h和ControlCAN.lib放在工程目录下,和源文件放在一起
2、把kerneldlls文件夹(里面只需要放ini配置文件和usbcan.dll文件即可)和ControlCAN.dll和可执行文件放在一起
3、右键Qt工程,添加库->外部库,在库文件中找到ControlCAN.lib文件路径,不勾选Mac和linux,不勾选为debug版本添加d作为后缀
4、下一步,确定。此时已经把路径加进去了
5、右键工程,添加已经存在文件,此时已经默认勾选了ControlCAN.h,确定即可
PS:
1、周立功提供的动态库很多变量类型没有定义的,比如DWORD,可以再ControlCAN.h中
#include "windows.h"//windows
#include "windef.h"//linux
2、打开ControlCAN.h时会提醒编码不正确,选择system编码就行了
PS:
1、时间标识:CAN盒子接收到当前帧的时间,这个时间是CAN盒子启动的时间,最小单位是0.1ms,比较准
如何将时间标识转为字符串:
QString MyMethod::getTimeStampStr(UINT TimeStamp)
{
QString resultStr = "";
int hour = TimeStamp/36000000;
int minute = (TimeStamp - hour*36000000)/600000;
int second = (TimeStamp - hour*36000000 - minute*600000)/10000;
int ms = (TimeStamp - hour*36000000 - minute*600000 - second*10000)/10;
int mms = (TimeStamp - hour*36000000 - minute*600000 - second*10000 - ms*10);
resultStr = QString("%1:").arg(hour,2,10,QChar('0'));//时
resultStr += QString("%1:").arg(minute,2,10,QChar('0'));//分
resultStr += QString("%1:").arg(second,2,10,QChar('0'));//秒
resultStr += QString("%1:").arg(ms,3,10,QChar('0'));//毫秒
resultStr += QString::number(mms);//0.1ms
return resultStr;
}
2、如何高速CAN通信
根据我在项目中的实践,发现利用PC里能达到的最块CAN通信(使用USBCAN-2)速度是1ms,但是需要很多技巧。
①、使用3个线程类:1个用来接收,1个用来发送,1个用来解析
②、接收线程最好使用最高线程权限:QThread::HighestPriority,其他的用第二高权限(这个根据计算机性能来考虑)
③、如何循环发送报文:在发送线程里再多加一个定时器(这个定时器不是主界面的,而是发送线程的),定时器timeout时间为需要循环发送的时间(可达到1ms);
用户在主界面设置需要发送的报文为OBJ结构体数组,然后通过狗仔函数的方式传到发送线程,最后发送就行了。
④、解析过程:接收函数循环接收报文,每接收到n帧就发送到解析线程,然后根据ID解析,将解析数据发送主界面显示(显示的时候textedit不要滚动,即不要append,直接替换,否则会卡顿)
PS:
1、打开两路CAN:VCI_OpenDevice只能调用一次,并且需要在同一个软件中使用(dll只能调用一次)
Qt配置USBCAN通信的更多相关文章
- Qt实现串口通信总结
Qt实现串口通信总结 注意: Qt5发布之前,Qt实现串口通信一般是采用第三方类库qextserialport.Qt5发布后自带了QtSerialPort 能够支持串口通信. 1.Qextserial ...
- vs与qt配置
1.error: these Qt version are inaccessible;Qt5.4.0 in D:\qt5.4.0\5.4\msvc2013Make sure that you have ...
- Qt 与 JavaScript 通信
使用QWebView加载网页后,解决Qt与JavaScript通信的问题: The QtWebKit Bridge :http://qt-project.org/doc/qt-4.8/qtwebkit ...
- QT实现TCP通信服务器端和客户端(支持多个客户端)精简版
上星期接了个私活,工期两星期,报酬3000,写一个小软件,采集定向网络上的数据,并进行双向通信,捣鼓了两天,终于把QT中tcp通信这块调通了,找过N多例子,绝大部分都是基本的一个服务端一个客户端通信的 ...
- Tomcat6和Tomcat7配置SSL通信的比较
<Tomcat6和Tomcat7配置SSL通信的比较> 作者:chszs,转载需注明.博客主页: http://blog.csdn.net/chszs 在项目开发过程中,尝尝会遇到Tomc ...
- Qt配置信息设置(QSettings在不同平台下的使用路径)
在Windows操作系统中,大多把配置文件信息写在注册表当中,或写在*.ini文件中,对于这两种操作都有相应的Windows API函数,在以前的文章中都提及过,这里就不多说了~ 在Qt中,提供了一个 ...
- Qt编写串口通信程序全程图文解说
(说明:我们的编程环境是windows xp下,在Qt Creator中进行,假设在Linux下或直接用源代码编写,程序稍有不同,请自己修改.) 在Qt中并没有特定的串口控制类,如今大部分人使用的是第 ...
- 转:Qt编写串口通信程序全程图文讲解
转载:http://blog.csdn.net/yafeilinux/article/details/4717706 作者:yafeilinux (说明:我们的编程环境是windows xp下,在Q ...
- QT之TCP通信
QT中可以通过TCP协议让服务器和客户端之间行通信.所以下面我就围绕服务器和客户端来写. 这是我么写服务器和客户端的具体流程: A.服务器: 1.创建QTcpServer对象 2.启动 ...
随机推荐
- c++通过类名动态创建对象
转载:http://www.seacha.com/article.php/knowledge/cbase/2013/0615/2154.html 主要思想:在每次创建类的过程中,通过各自类的辅助类(所 ...
- 去OpenCVManager,大部分为转载,仅当自己学习使用
去OpenCVManager方法,可以参考这篇博客http://blog.csdn.net/yanzi1225627/article/details/27863615,可以用,挺好的.我这里只是做个总 ...
- Map的两张遍历方法 keySet(),entrySet()
源博客 http://blog.csdn.net/liu826710/article/details/9001254 在Map集合中 values():方法是获取集合中的所有的值----没有键,没有对 ...
- VS2008试用版到期解决办法----win7下VS2008升级补丁.zip
打开好久没用的Visual studio 2008,才知道试用版已经到期了.在网上找来了序列号,可是连一个输入序列号的地方都没有,困惑了好久,终于找到了解决办法. 首先献上自己收集的Visual st ...
- CodeIgniter框架——函数(时间函数、装载函数)剖析+小知识点
连接数据库: 格式: mysql -h主机地址 -u用户名-p用户密码 数据库的提示符:mysql> 退出数据库: exit(回车) 知识点积累: 1.date_default_timezone ...
- 《从零开始学Swift》学习笔记(Day 41)——类的继承
原创文章,欢迎转载.转载请注明:关东升的博客 Swift中的继承只能发生在类上,不能发生在枚举和结构体上.一个类可以继承另一个类的方法.属性.下标等特征,当一个类继承其他类时,继承类叫子类,被继承类叫 ...
- IIPP迷你项目(二)"Guess the Number!"
本来这个程序是早就编完了的,一直没时间发布博客.时至今日已时隔多天,也算是复习一下事件驱动型编程的过程吧. 1 事件驱动型编程 本质上这次的作业是披着猜数字皮的图形化界面编程,好在 simplegui ...
- JS将秒转换为 天
function SecondToDate(msd) { var time =msd if (null != time && " ...
- Pycharm中目前用到的快捷键
1.批量注释:Ctrl+/ 2.缩进\不缩进:Tab\Shift+Tab 3.运行:Ctrl+Shift+F10 4.撤销\反撤销:Ctrl+z\Ctrl+shift+z 5.当光标在代码中间,如何回 ...
- Exploiting second-order SQL injection 利用二阶注入获取数据库版本信息 SQL Injection Attacks and Defense Second Edition
w SQL Injection Attacks and Defense Second Edition Exploiting second-order SQL injection Virtually ...