Board logo

标题: WindowsCE.Net下CAN卡的驱动程序设计(2) [打印本页]

作者: yuyang911220    时间: 2016-11-21 10:49     标题: WindowsCE.Net下CAN卡的驱动程序设计(2)

BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)

{

BOOL bSuc=FALSE;

ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防错处理*/

if(0= =(hCan->dwAccessCode & GENERIC_WRITE))

return FALSE;

:: EnterCriticalSection(&hCan->lpCanHWInfo->

TransmitCritSec); /*进入临界区*/

BYTE byV=static_cast<BYTE>(1pMsg->dwMsgID>>3);

CANW(hCan,10,byV); /*设置ID值高8位*/

byV=static_cast<BYTE>=((lpMsg->dwMsgID & 7)<<5);

if(lpMsg->bRTR) byV|=0x10;

byV+=static_cast<BYTE>(lpMsg->dwMessageLen);

CANW(hCan,11,byV);/*设置ID值低3位、RTR及数据长度*/

for(UINT i=0;<lpMsg->dwMessageLen;++i)

{

CANW(hCan,12+i,lpMsg->byMsg[i]);

} /*采集数据*/

CANW(hCan,1,1);/*重置传输请求*/

while(TRUE)

{byV=CANR(hCan,2);

if(byV & 0X40) /*传输缓冲区满,退出*/

{break;}

if(byV & 0X8){ /*传输结束,正确返回退出*/

bSuc = TRUE;

break;}

}

:eaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*离开临界区*/

return bSuc;

}

2.4 CAN卡信息接收

CAN卡的信息接收是发送的逆过程,当接收缓冲区标志为1时,表示缓冲区已满可以接收数据,将数据接收到数组后释放接收缓冲区,然后对接收到的数据进行分解并存储到CAN卡信息缓冲区的结构体。接收缓冲区的寄存器结构如表2所列。

CAN消息接收函数的实现如下:

BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO

HCan,OUT LPCanCardMessageBuflpMsg)

{……

if(CANR(hCan,2)&1){ /*判断接收缓冲区是否已满*/

for(UINT i=0;i<10;++i)

recvBuf[i]=CANR(hCan,20+i);/*将数据暂存到临时缓冲区*/

CANW(hCan,1,4); /*释放接收缓冲区*/

LpMsg->dwMsgID=recvBuf[0]<<3; /*取出ID的高8位*/

BYTE byV =recvBuf[1];

LpMsg->dwMsgID+=byV >>5;/*取出ID低3位,然后和高8位合并*/

LpMsg->bRTR =byV &0x10?TRUE:/*返回RTR状态*/

LpMsg->dwMessageLen = byV &0XF; /*返回数据长度*/

……

}

else

{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*没有收到数据,错误计数加1*/

::LeaveCriticalSection(&hCan->lpCanHWInfo->

ReceiveCritSec); /*离开临界区*/

Return bSuc;

}

2.5 CAN卡事件处理

CAN卡事件处理函数是CAN卡驱动程序中很重要的部分。驱动设计要求具有消息通知的功能,当事件发生时及时捕获事件并进行消息处理。

下面是事件处理函数的实现:

staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)

{

ASSERT(lpParam);

LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;

CanCardMessageBuf bufMsg;

while(TEUE)

{ /*循环等待CAN卡消息产生,然后进行处理*/

::WaitForSingleObject(hCan->lpCanHWInfo->hCanEvent,0XFFFFFFFF);

if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN线程已关闭则中断*/

if(CAN_RecvMessage(hCan,&hufMsg)){ /*正确接收数据后*/

CAN_RecvBufPush(hCan,&bufMsg);} /*将数据压入缓冲*/

BYTE byV=CANR(hCan,3); /*将3号寄存器读出然后立即写入*/

CANW(hCan,3,byV);/*能够获取每次中断*/

InterruptDone(hCan->lpCanHWInfo->lpCanObj->dwSysIrqt);

} /*本次中断结束,等待下次中断*/

return 0;

}

2.6 其它函数

为了提供更多的功能和更方便地使用CAN卡进行通信,在CAN卡驱动程序中还设计了一些函数如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于处理接收缓冲区、CAN_Reset用于复位CAN卡、CheckHWInfo用于硬件信息检查等。这些函数提供了对CAN通信卡的设置、检查等功能,在这里不再详述了。

3 CAN卡驱动封装设计

CAN卡底层驱动函数虽然功能完整,但是对于用户使用比较复杂并且一般用户不需要了解底层实现的机制。为了便于使用,最后对CAN卡的驱动进行了封装,提供CanOpenFile、CanSendMsg等五个函数用于CAN总线的通信,以动态连接库(DLL)的形式提供给用户调用。封装函数及功能如下:

*CanOpenFile;初始化并打开CAN卡的一个端口。

*CanCloseFile;关闭由CanOpenFile打开的CAN卡端口。

*CanRecvMsg;接收CAN卡数据,打开CAN卡时必须具有GENERIC_READ权限。

*CanSendMsg;通过CAN卡发送数据。打开CAN卡时必须具有GENERIC_WRITE权限。

*CanIOControl;设置或获取CAN卡I/O参数支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。

下面是CanSendMsg函数实现的代码:

BOOL CanSendMSg(

HANDLE hCan,

LPCanCardMessageBuflpMsg)

{

if(!hCan||INVALID_HANDLE_VALUE= =hCan||

!lpMsg||lpMsg->dwMessageLen>8)return FALSE;

return CAN_SendMessage(LPCAN_HW_OPEN_INFO)

hCan,lpMsg);

该函数就是通过封装CAN卡的底层驱动函数SendMessage来实现的,这样将功能集中的五个函数更方便了用户使用。

结语

程序开发的上位机是普通的PC机,软件环境是:Windows2000 Professional、Embedded Visual C++4.0、与下位机中WinCE.NET对应的SDK,该SDK是在用Platform Builder 4.0定制WinCE时编译生成的。下位机使用的硬件是研华的嵌入式PC104主板PCM3346N,操作系统为WinCE.ENT。

本文设计开发的驱动已经在北京怀柔的变电站项目中得到成功的应用,CAN卡通信稳定,系统在WINCE.NET下运行可靠,保证了项目的顺利实施。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0