完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
用户可从英创开发光盘中或联系英创工程师获得CAN例程源码。参考例程使用英创已经封装好的.h及.cpp库文件可以使开发更方便。 注册表设置项说明 CAN驱动设置参数位于注册表[HKEY_LOCAL_MACHINEDriversBuiltinCAN1]及[HKEY_LOCAL_MACHINEDriversBuiltInCAN2]下 主要配置参数项: TxTimeout :发送超时时间,单位ms。 BusErrorReport :错误帧上报标记,0:不上报,1:上报错误帧 设置程序可以连接英创工程师获得。 CAN打开及关闭 打开关闭采用标准的流式设备驱动接口CreateFile及CloseHandle,设备名为”CAN1:”及”CAN2:” 调用示例如下: //打开CAN1 HANDLE hCan; hCan = CreateFile( L”CAN1:”, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
//关闭CAN CloseHandle(hCan); CAN波特率设置 参考CAN例程,对驱动的DeviceIoCon trol操作已封装在SetBaud函数中。 BOOL SetBaud(HANDLE hCan, DWORD dwBaud) 参数hCan:CreateFile打开CAN返回的设备句柄 参数dwBaud:波特率,单位bps 返回值:TRUE 设置成功,FALSE 设置失败 调用示例如下: //设置波特率250bps CAN SetBaud(m_hCan, 250000); CAN过滤设置 调用方法 参考CAN例程,对驱动的DeviceIoCon trol操作已封装在SetFilter函数中。 BOOL SetFilter(HANDLE hCan, PCAN_FILTER pFilter, DWORD num) 参数hCan:CreateFile打开CAN返回的设备句柄 参数pFilter:过滤器结构体数组指针 参数num:过滤器结构体数组长度,最大为4 返回值:TRUE 设置成功,FALSE 设置失败 注:此函数如果重复调用,生效的为最后一次调用设置值。 CAN_FILTER过滤器结构体定义 typedef struct _can_filter { CAN_ID can_id; CAN_ID can_mask; } CAN_FILTER, *PCAN_FILTER 过滤器由id和mask组成,设置的过滤器组数最大4个。CAN包能满足其中一组过滤器以下条件才能接收 CAN包id & 过滤器mask = 过滤器id 即,2进制中,过滤MASK为1的对应位需和过滤ID值一致,示例表 调用示例如下 //设置一组寄存器 CAN_FILTER Filter[4]; memzero(Filter, sizeof(CAN_FILTER)); Filter[0].can_id.id = 5; Filter[0].can_mask.id = 22; SetFilter(m_hCan, Filter, 1); CAN发送/接收 发送接收同样采用标准的流式设备驱动接口ReadFile及WriteFile 调用方法 参考CAN例程,封装好的函数定义。 int WriteCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){ DWORD dwLen; if(!WriteFile( hCan, (char *)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 )) return 0; return dwLen/sizeof(CAN_FRAME); }
int ReadCAN(HANDLE hCan, PCAN_FRAME pFrame, DWORD num){ DWORD dwLen; if(!ReadFile( hCan, (char *)pFrame, num*sizeof(CAN_FRAME), &dwLen, 0 )) return 0; return dwLen/sizeof(CAN_FRAME); } 参数hCan:CreateFile打开CAN返回的设备句柄 参数pFrame:帧结构体数组指针 参数num:帧结构体数组长度,默认值1,可空 返回值:发送/接收的数据包个数 注:发送函数为阻塞函数,超时时间可以在注册表中设置,默认1000ms。 发送失败后,应用程序应当自行判断是否需要重新发送。 接收函数应当单独开一个接收线程,并配合WaitCANEvent函数使用,参考下一节。 CAN_FRAME数据帧结构体定义 typedef struct{ unsigned int id:29; unsigned int error:1; unsigned int remote:1; unsigned int extended:1; }CAN_ID;
typedef struct _can_frame { CAN_ID can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ BYTE can_dlc; /* frame payload length in byte (0 ..CAN_MAX_DLEN) */ BYTE data[CAN_MAX_DLEN]; } CAN_FRAME, *PCAN_FRAME;
调用示例如下: DWORD dwNum; //发送 CAN_FRAME Sendframe; memzero(Sendframe, sizeof(CAN_FRAME)); Sendframe.can_id.id = 6; m_Sendframe.data[0] = 0x01; m_Sendframe.can_dlc = 1; dwNum = WriteCAN(hCan, &Sendframe);
//接收 CAN_FRAME Revframe[MAX_ARRAY]; dwNum = ReadCAN(hCan, Revframe, MAX_ARRAY);
WaitCANEvent函数使用 如果轮询方式接收CAN包,系统负荷会过高,采用事件方式事半功 WaitCANEvent为等待CAN接收事件的阻塞函数,通过返回值可以判断是否有CAN数据接收。 BOOL WaitCANEvent( HANDLE hDevice, LPDWORD lpEvtMask, DWORD dwTimeout ) 参数hDevice:CreateFile打开CAN返回的设备句柄 参数lpEvtMask:返回事件类型,新驱动目前恒为0 参数dwTimeout:超时时间 返回值:FALSE 等待超时,TRUE 有数据帧收到 接收线程调用示例 //主线程中开启接收线程 m_hRecvThread = CreateThread(0, 0, RecvTread, this, 0, NULL);
//接收线程函数定义 DWORD Ctest_can_v2Dlg::RecvTread(LPVOID lparam) { Ctest_can_v2Dlg* pDlg = (Ctest_can_v2Dlg*)lparam; DWORD dwEvtMask; int num; CAN_FRAME rbuf[MAX_ARRAY];
while(!pDlg->m_bThreadStop) { if(WaitCANEvent(pDlg->m_hCan, &dwEvtMask, 200)) { if( dwEvtMask == 0 ) // 接收到数据包 { num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY); while( num ) { OnRecv(pDlg, rbuf, num); //调用回调函数处理数据 num = ReadCAN(pDlg->m_hCan, rbuf, MAX_ARRAY); } } else //258 { } } } return 0; } 错误帧定义 当设置注册表选项,允许接收错误帧后,CAN总线上的出错信息将以帧的形式上报上来。 错误帧的帧结构体中,值为1,可通过该值判断是接收到的数据帧还是驱动上报的错误帧。 if(Frame.can_id.error){ //错误帧 } else{ //数据帧; } 错误帧详细定义,请参数手册《CAN错误帧定义》。 精简掉的接口 新CAN驱动能够自动复位CAN总线,不需要再手动复位,所以之前ResetCAN,StartCAN,StopCAN精简掉了。 SetCANLoop功能实用性不大,故精简掉。 但是为了兼容老驱动,这些函数依然可以正常调用。 相关测试例程可以联系英创工程师获得。 成都英创信息技术有限公司 http://www.emtronix.com |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 10:52 , Processed in 0.601110 second(s), Total 44, Slave 32 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号