如何在VC下使用USB-CAN II接口卡操作CAN通信
广州致远电子的USB-CAN II接口卡是比较普遍的CAN采集,测试工具,在进行有关CAN的开发中经常用使用到此设备。然而如何在VC中调用此设备提供的API呢?其实很简单,有关它的API介绍及使用手册在http://www.embedcontrol.com/products/PCI/USBCAN.asp 这个网址可以找到,这里只介绍它的使用示例。
1 连接USB-CAN II设备
示例代码如下:
void Ctbox_CarSimulatorDlg::OnBnClickedBtConnect() { // TODO: Add your control notification handler code here if(m_connect ==true){ //如果已经连接 m_connect =false; Sleep(500); GetDlgItem(IDC_BT_CONNECT)->SetWindowText("连接"); VCI_CloseDevice(VCI_USBCAN2,0); return; } //如果未连接 UpdateData(true); VCI_INIT_CONFIG init_config; memset(&init_config,0,sizeof(VCI_INIT_CONFIG)); init_config.AccCode=0; //验收码 init_config.AccMask=0xffffffff; //屏蔽码 init_config.Filter=1; //过滤方式 init_config.Mode=0; //模式 init_config.Timing0=0; //定时器0 init_config.Timing1=0x1c; //定时器1 //打开设备 if(VCI_OpenDevice(VCI_USBCAN2,0,0)!=STATUS_OK) { MessageBox("打开设备失败!","警告",MB_OK|MB_ICONQUESTION); return; } //初始化CAN if(VCI_InitCAN(VCI_USBCAN2,0,m_channel_sel,&init_config)!=STATUS_OK) { MessageBox("初始化CAN失败!","警告",MB_OK|MB_ICONQUESTION); VCI_CloseDevice(0,0); return; } //启动CAN if(VCI_StartCAN(VCI_USBCAN2,0,m_channel_sel)!=1) { MessageBox("启动CAN失败!","警告",MB_OK|MB_ICONQUESTION); VCI_CloseDevice(0,0); return; } m_connect=1; GetDlgItem(IDC_BT_CONNECT)->SetWindowText("断开"); }
注:这里,定时器0必须设备为0,定时器必须设备为0x1c,在PC上才能正常工作,不然调用发送接口时老是会返回错误。
2 发送CAN消息
VCI_CAN_OBJ frameinfo; frameinfo.DataLen =8; frameinfo.RemoteFlag =0; frameinfo.ExternFlag =0; frameinfo.SendType =0; frameinfo.ID =CAN_ID_LOCK; frameinfo.Data[1] =lock; VCI_Transmit(VCI_USBCAN2,0,dlg->m_channel_sel,&frameinfo,1);
3 接收CAN消息
接收CAN消息一般是通过个线程来实现,如下:
UINT Ctbox_CarSimulatorDlg::ReceiveThread(void * param) { Ctbox_CarSimulatorDlg *dlg =(Ctbox_CarSimulatorDlg *)param; VCI_CAN_OBJ frameinfo[50]; VCI_ERR_INFO errinfo; int len=1; int i=0; while(1){ Sleep(100); if(!dlg->m_connect){ continue; } len=VCI_Receive(VCI_USBCAN2,0,dlg->m_channel_sel,frameinfo,50,200); if(len<=0){ //注意:如果没有读到数据则必须调用此函数来读取出当前的错误码, //千万不能省略这一步(即使你可能不想知道错误码是什么) VCI_ReadErrInfo(VCI_USBCAN2,0,dlg->m_channel_sel,&errinfo); } else{ //数据处理 for(i=0;i<len;i++){ switch(frameinfo[i].ID){ case CANID_RC_HEAD_LIGHT: case CANID_RC_HORN: case CANID_RC_LOCK: dlg->m_remote_control_page.SetStatus(frameinfo[i].ID,8,frameinfo[i].Data); break; default: break; } } } } return 0; }
在对话框的初始化函数中启动此接收线程:
AfxBeginThread(ReceiveThread,this);
4 复位CAN
void Ctbox_CarSimulatorDlg::OnBnClickedBtReset() { // TODO: Add your control notification handler code here if(m_connect==0){ AfxMessageBox("还未连接!",0); return; } //复位CAN if(VCI_ResetCAN(VCI_USBCAN2,0,m_channel_sel)!=1) { AfxMessageBox("复位失败",0); } //启动CAN if(VCI_StartCAN(VCI_USBCAN2,0,m_channel_sel)!=1) { MessageBox("启动CAN失败!","警告",MB_OK|MB_ICONQUESTION); VCI_CloseDevice(0,0); return; } AfxMessageBox("复位成功",0); }
5 其它
工程中必须包含SDK中提供到lib文件及头文.
即可VS2010的工程属性页面的Linker->Input->Addtional Dependencies一栏中设置为:./ControlCAN.lib;%(AdditionalDependencies)
然后将.cpp文件中包含头文:
#include "ControlCAN.h"
最后需要将USB-CAN II SDK中提供的ControlCAN.dll及kerneldlls文件夹拷贝到工程目录下,程序才能正常运行。
如上示例代码即可操作USB-CAN II设备。
USBCAN-2E-U与USBCAN-II的使用区别
USBCAN-II已经停产,目前它的升级版本为USBCAN-2E-U,之前我有过一篇文章讨论USBCAN-II的使用方法,见:点http://blog.csdn.net/flydream0/article/details/8088248.本文的目的是讨论两者在使用上的区别,以便将原有的USBCAN-II的源码移植到USBCAN-2E-U上来.
仔细看了下USBCAN-2E-U的开发手册,发现相对于USBCAN-II来说,在初始化时,USBCAN-2E-U必须设置波特率,否则不能正常通信,设置波特率是通过VCI_SetReference接口来实现的,函数原型为:
DWORD __stdcallVCI_SetReference(DWORD DevType,DWORD DevIndex,DWORD CANIndex,DWORD RefType,PVOID pData);
这个函数本来是设置相关参加的意思,在不同的设备类型具有不同的含义,但在DevType=USBCAN-2E-U,且RefType=0时表示设置波特率的含义:
一个实始化的实例如下:
//打开设备 if(VCI_OpenDevice(m_devtype,index,0)!=STATUS_OK) { MessageBox("打开设备失败!","警告",MB_OK|MB_ICONQUESTION); return; } //设置波特率 if(m_devtype ==VCI_USBCAN_2E_U) { DWORD baud =0x060007; if (VCI_SetReference(m_devtype,index, cannum, 0, &baud) != STATUS_OK) { MessageBox(_T("设置波特率错误,打开设备失败!"), _T("警告"), MB_OK | MB_ICONQUESTION); VCI_CloseDevice(m_devtype,index); return; } } //初始化CAN if(VCI_InitCAN(m_devtype,index,cannum,&init_config)!=STATUS_OK) { MessageBox("初始化CAN失败!","警告",MB_OK|MB_ICONQUESTION); VCI_CloseDevice(m_devtype,index); return; } //... //启动CAN if(VCI_StartCAN(m_devtype,m_devind,m_cannum)==1) { ShowInfo("启动成功",0); } else { CString str; str="启动失败"; ShowInfo(str,2); }只要在初始化部分增加设置波特率操作,就能将USBCAN-II的源码很好的移植到USBCAN-2E-U上了.
其它的,接收过滤器上的接口也做了优化,这里就不做详情介绍了.