<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
關(guān) 閉

新聞中心

EEPW首頁(yè) > 工控自動(dòng)化 > 設計應用 > WindowsCE.Net下CAN卡的驅動(dòng)程序設計

WindowsCE.Net下CAN卡的驅動(dòng)程序設計

作者: 時(shí)間:2004-12-07 來(lái)源:網(wǎng)絡(luò ) 收藏
摘要:主要討論在WinCE設計和開(kāi)發(fā)卡通信程序的方法;詳細介紹卡底層函數的設計和實(shí)現,同時(shí)將進(jìn)行封裝,用動(dòng)態(tài)庫的方式提供給用戶(hù)卡通信用的,使用啟可以方便地在自己的程序中調用,實(shí)現WinCE下的CAN卡通信。

關(guān)鍵詞:WinCE.NET CAN 驅動(dòng)

引言

近年來(lái)電力行業(yè)為了快速部署變電站,采用了建造整體變電所的方法:在生產(chǎn)基地將變電站的內部設備安裝、調試完成,只留下與外界的接口,整體運到變電站所在地后進(jìn)行安裝和簡(jiǎn)單調試即可投入運行。其內部設備通過(guò)CAN總線(xiàn)進(jìn)行通信,系統原有的監控軟件基于DOS系統,維護調試比較困難,因此想要尋求更方便、友好的系統支持。經(jīng)過(guò)比較,嵌入式操作系統市場(chǎng)上風(fēng)頭正勁的Windows CE .NET成為最終選擇。微軟的最新產(chǎn)品Windows CE.NET提供了端對端的開(kāi)發(fā)、調試手段,可以不拆卸設備的情況下通過(guò)Telnet登錄到上進(jìn)行調試和維護,其系統本身為嵌入式市場(chǎng)進(jìn)行重新設計,包括創(chuàng )建一個(gè)基于的定制設備所需的一切。這樣就需要將原來(lái)DOS下的程序移植到.NET下,但是各個(gè)硬件廠(chǎng)商目前還沒(méi)有提供CAN通信卡在Windows CE.NET下的驅動(dòng),所以開(kāi)發(fā)Windows CE.NET下的CAN卡驅動(dòng)成為項目推行中的關(guān)鍵一環(huán)。

本文主要針對研華的雙口CAN卡PCM3680進(jìn)行分析,介紹在WindowsCE.ENT系統下進(jìn)行底層設備驅動(dòng)開(kāi)發(fā)的方法并提供CAN通信的實(shí)例。

1 CAN總線(xiàn)通信協(xié)議及CAN通信卡介紹

CAN總線(xiàn)是德國B(niǎo)osch公司20世紀80年代初為解決現代汽車(chē)中眾多的控制與測試儀器之間的數據交換而開(kāi)的一種串行數據通信協(xié)議。它是一種多主總線(xiàn),廢除了傳統的站地址編碼,而代之以對通信數據塊進(jìn)行編碼。這種方法使網(wǎng)絡(luò )內節點(diǎn)個(gè)數在理論上不受限制,擴展格式中的29位的標識碼便可以定義2 29個(gè)不同的數據塊。

在本項目中使用的是研華的PCM3680,這是一塊嵌入式PC104的雙口CAN總線(xiàn)通信卡;CAN控制器采用Philips的獨立CAN控制器SJA1000芯片;CAN收發(fā)器采用Philips的P82C250,可以同時(shí)操作兩個(gè)CAN網(wǎng)絡(luò ),提供高達1Mb/s的傳輸速度。PCM3680支持很寬的中斷范圍:中斷3、4、5、6、7、9、10、11、12、15,同時(shí)1000V的光電隔離提供系統高可靠性。在CAN卡通信中,要用到CAN控制器中的很多寄存器,各個(gè)寄存器的含義和作用可以參考控制芯片的說(shuō)明書(shū)。圖1列出驅動(dòng)程序設計中用到最主要的寄存器結構。

2 CAN卡驅動(dòng)底層函數設計

本方案設計CAN驅動(dòng)是放在Windows CE操作系統的內核下層,位于OEM adaptation layer(OAL)層的一個(gè)真正的驅動(dòng),而不是在主程序中的串口操作。在Windows CE的設備管理器可以看到CAN1和CAN2兩個(gè)端口,并且可以查看其工作的正常與否和對其進(jìn)行配置。如:中斷號和I/O地址。

2.1 CAN卡寄存器讀寫(xiě)函數

CAN卡的通信是通過(guò)操作CAN卡上的CAN控制器進(jìn)行的。在CAN控制器中有很多寄存器,如控制寄存器、命令寄存器、狀態(tài)寄存器、中斷寄存器等,通過(guò)讀寫(xiě)這些寄存器中的命令狀態(tài)字可以檢測和控制CAN卡的行為。在Windows CE.NET下,通過(guò)調用DOK中的API函數HalTranslateBusAddress,將CAN卡分配的物理地址映射為邏輯地址。這樣各個(gè)寄存器對應的就是CAN卡基地址的偏移地址,因此,對寄存器的讀寫(xiě)就轉化為對內存地址的讀寫(xiě)。下面是CAN卡寄存器的讀寫(xiě)函數:

*在偏移量為off的地址讀取一個(gè)字節的數據inline BYTE CANR(LPCAN_HW_OPEN_INFO hCan,DWORD off)

{

return hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off];

*將一個(gè)字節數據寫(xiě)到偏移量為off的地址中inline VOID CANW(LPCAN_HW_OPEN_INFO hCan,DWORD off,BYTE val)

{

hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr[off]=val;

}

參數LPCAN_HW_OPEN_INFO定義的是CAN卡的數據結構,其中成員lpMappeBaseAddr[0]表示的是映射后基地址,lpMappedBaseAddr[1]就是基地址+1的地址,對應CAN卡的寄存器是命令寄存器。通過(guò)上述兩個(gè)函數可操作CAN卡上的所有寄存器。

2.2 CAN卡初始化

CAN卡的控制器比較復雜,在通信前必須確認硬件信息正確性、初始化各寄存器。初始化函數的基本流程如圖3所示。

第一步,檢查端口號和硬件信息的正確性,主要是CAN卡中斷號是否有效。

第二卡,設置CAN卡默認參數:

CanCardConfigInfo CAN_DEFAULT_SETTING=

{0X00,0XFF,0X03,0X1C};/*設置默認波特率為125Kbps*/

DWORD dwThreadID =0;

PHYSICAL_ADDRESS phyAddr={hwInfo->dwIOBaseAddr *16,0 };

第三卡,用WinCE API函數LocalAlloc為CAN卡驅動(dòng)中用到的數據結構分配緩沖區;通過(guò)HalTranslateBusAddress和MmMapIoSpace函數映射I/O地址,提供直接訪(fǎng)問(wèn)設備的虛擬地址:

if(!HalTranslateBusAddress(Isa,0,phyAddr,0,phyAddr))

goto _ExitInit;

hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr=

(LPBYTE)MmMapIoSpace(phyAddr,CANCARDADDRLEN,FALSE);

if(!hCan->lpCanHWInfo->lpCanObj->lpMappedBaseAddr)

goto _ExitInit;

如果分配內存或映射邏輯地址失敗,則退出初始化程序,CAN卡初始化失敗。

第四步,初始化讀寫(xiě)屬性、共享模式、讀超時(shí)時(shí)間和第二個(gè)CAN口的基地址。

第五步,創(chuàng )建CAN卡事件和數據接收事件:hCan->lpCanHWInfo->hCanEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

hCan->lpCanHWInfo->hRecvMsgEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

第六步,初始化中斷,如果CAN卡有復位請求就退出初始化程序。設置好中斷后啟動(dòng)數據接收線(xiàn)程,設置線(xiàn)程優(yōu)先級繼續線(xiàn)程處理;最后配置CAN卡參數,進(jìn)入正常運行狀態(tài)。

2.3 CAN卡信息發(fā)送

CAN卡的信息發(fā)送分為兩個(gè)步驟。在對CAN卡基本信息進(jìn)行檢查后,首先設置發(fā)送緩沖的ID號。CAN標準模式的ID號為11位,偏移地址10中存放的是ID號的高8位,偏移地址11的高3位存放的是ID號的低3位,剩下5位分別是RTR位(遠程傳送請求位)和數據長(cháng)度。通過(guò)CANW函數將處理后的數據寫(xiě)入到相應的偏移地址,設置完相應的地址數據后,通過(guò)循環(huán)將偏移地址12~19的數據采集回來(lái)存到數組中。然后,設置CAN卡的傳輸請求為允許并不斷偵測狀態(tài)寄存器的變化,當傳輸緩沖滿(mǎn)標志或傳輸結束標志為1時(shí)通出程序,完成一次數據采集。傳輸緩沖區的寄存器如表1所列。

表1

ID號10ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3
RTR,數據長(cháng)度碼11ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0
數據1~812~19數據數據數據數據數據數據數據數據

表2

ID號20ID.10ID.9ID.8ID.7ID.6ID.5ID.4ID.3
RTR,數據長(cháng)度碼21ID.2ID.1ID.0RTRDLC.3DLC.2DLC.1DLC.0
數據1~822~29數據數據數據數據數據數據數據數據

CAN消息發(fā)送函數的實(shí)現如下:

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); /*進(jìn)入臨界區*/

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

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

byV=static_castBYTE>=((lpMsg->dwMsgID 7)5);

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

byV+=static_castBYTE>(lpMsg->dwMessageLen);

CANW(hCan,11,byV);/*設置ID值低3位、RTR及數據長(cháng)度*/

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) /*傳輸緩沖區滿(mǎn),退出*/

{break;}

if(byV 0X8){ /*傳輸結束,正確返回退出*/

bSuc = TRUE;

break;}

}

::LeaveCriticalSection(hCan->lpCanHWInfo->TransmitCritSec); /*離開(kāi)臨界區*/

return bSuc;

}

2.4 CAN卡信息接收

CAN卡的信息接收是發(fā)送的逆過(guò)程,當接收緩沖區標志為1時(shí),表示緩沖區已滿(mǎn)可以接收數據,將數據接收到數組后釋放接收緩沖區,然后對接收到的數據進(jìn)行分解并存儲到CAN卡信息緩沖區的結構體。接收緩沖區的寄存器結構如表2所列。

CAN消息接收函數的實(shí)現如下:

BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO

HCan,OUT LPCanCardMessageBuflpMsg)

{……

if(CANR(hCan,2)1){ /*判斷接收緩沖區是否已滿(mǎn)*/

for(UINT i=0;i10;++i)

recvBuf[i]=CANR(hCan,20+i);/*將數據暫存到臨時(shí)緩沖區*/

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狀態(tài)*/

LpMsg->dwMessageLen = byV 0XF; /*返回數據長(cháng)度*/

……

}

else

{++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒(méi)有收到數據,錯誤計數加1*/

::LeaveCriticalSection(hCan->lpCanHWInfo->

ReceiveCritSec); /*離開(kāi)臨界區*/

Return bSuc;

}

2.5 CAN卡事件處理

CAN卡事件處理函數是CAN卡驅動(dòng)程序中很重要的部分。驅動(dòng)設計要求具有消息通知的功能,當事件發(fā)生時(shí)及時(shí)捕獲事件并進(jìn)行消息處理。

下面是事件處理函數的實(shí)現:

staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)

{

ASSERT(lpParam);

LPCAN_HW_OPEN_INFO hCan=(LPCAN_HW_OPEN_INFO)lpParam;

CanCardMessageBuf bufMsg;

while(TEUE)

{ /*循環(huán)等待CAN卡消息產(chǎn)生,然后進(jìn)行處理*/

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

if(hCan->lpCanHWInfo->bKillCanThread) break; /*若CAN線(xiàn)程已關(guān)閉則中斷*/

if(CAN_RecvMessage(hCan,hufMsg)){ /*正確接收數據后*/

CAN_RecvBufPush(hCan,bufMsg);} /*將數據壓入緩沖*/

BYTE byV=CANR(hCan,3); /*將3號寄存器讀出然后立即寫(xiě)入*/

CANW(hCan,3,byV);/*能夠獲取每次中斷*/

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

} /*本次中斷結束,等待下次中斷*/

return 0;

}

2.6 其它函數

為了提供更多的功能和更方便地使用CAN卡進(jìn)行通信,在CAN卡驅動(dòng)程序中還設計了一些函數如CAN_Config用CAN卡信息配置、CAN_RecvBufPop用于處理接收緩沖區、CAN_Reset用于復位CAN卡、CheckHWInfo用于硬件信息檢查等。這些函數提供了對CAN通信卡的設置、檢查等功能,在這里不再詳述了。

3 CAN卡驅動(dòng)封裝設計

CAN卡底層驅動(dòng)函數雖然功能完整,但是對于用戶(hù)使用比較復雜并且一般用戶(hù)不需要了解底層實(shí)現的機制。為了便于使用,最后對CAN卡的驅動(dòng)進(jìn)行了封裝,提供CanOpenFile、CanSendMsg等五個(gè)函數用于CAN總線(xiàn)的通信,以動(dòng)態(tài)連接庫(DLL)的形式提供給用戶(hù)調用。封裝函數及功能如下:

*CanOpenFile;初始化并打開(kāi)CAN卡的一個(gè)端口。

*CanCloseFile;關(guān)閉由CanOpenFile打開(kāi)的CAN卡端口。

*CanRecvMsg;接收CAN卡數據,打開(kāi)CAN卡時(shí)必須具有GENERIC_READ權限。

*CanSendMsg;通過(guò)CAN卡發(fā)送數據。打開(kāi)CAN卡時(shí)必須具有GENERIC_WRITE權限。

*CanIOControl;設置或獲取CAN卡I/O參數支持的I/O控制包括:IOCTL_CAN_CONFIG,IOCTL_CAN_RESET,IOCTL_CAN_TIMEOUT,IOCTL_CAN_SENDREADY,IOCTL_CAN_RECVREADY。

下面是CanSendMsg函數實(shí)現的代碼:

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);

該函數就是通過(guò)封裝CAN卡的底層驅動(dòng)函數SendMessage來(lái)實(shí)現的,這樣將功能集中的五個(gè)函數更方便了用戶(hù)使用。

結語(yǔ)

程序開(kāi)發(fā)的上位機是普通的PC機,軟件環(huán)境是:Windows2000 Professional、Embedded Visual C++4.0、與下位機中WinCE.NET對應的SDK,該SDK是在用Platform Builder 4.0定制WinCE時(shí)編譯生成的。下位機使用的硬件是研華的嵌入式PC104主板PCM3346N,操作系統為WinCE.ENT。

本文設計開(kāi)發(fā)的驅動(dòng)已經(jīng)在北京懷柔的變電站項目中得到成功的應用,CAN卡通信穩定,系統在WINCE.NET下運行可靠,保證了項目的順利實(shí)施。



關(guān)鍵詞: WindowsCE Net CAN 驅動(dòng)

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>