<dfn id="is4kg"></dfn>
  • <ul id="is4kg"></ul>
  • <abbr id="is4kg"></abbr>
  • <ul id="is4kg"></ul>
    <bdo id="is4kg"></bdo>
    以文本方式查看主題

    -  曙海教育集團(tuán)論壇  (http://www.hufushizhe.com/bbs/index.asp)
    --  Wince技術(shù)討論區(qū)  (http://www.hufushizhe.com/bbs/list.asp?boardid=9)
    ----  主要討論在WinCE設(shè)計(jì)和開發(fā)C...WindowsCE.Net下CAN卡的驅(qū)動(dòng)程序設(shè)計(jì)31028  (http://www.hufushizhe.com/bbs/dispbbs.asp?boardid=9&id=1392)

    --  作者:wangxinxin
    --  發(fā)布時(shí)間:2010-11-16 14:31:36
    --  主要討論在WinCE設(shè)計(jì)和開發(fā)C...WindowsCE.Net下CAN卡的驅(qū)動(dòng)程序設(shè)計(jì)31028
    3、4、5、6、7、9、10、11、12、15,同時(shí)1000V的光電隔離提供系統(tǒng)高可靠性。在CAN卡通信中,要用到CAN控制器中的很多寄存器,各個(gè)寄存器的含義和作用可以參考控制芯片的說明書。圖1列出驅(qū)動(dòng)程序設(shè)計(jì)中用到最主要的寄存器結(jié)構(gòu)。

    2 CAN卡驅(qū)動(dòng)底層函數(shù)設(shè)計(jì)

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

    2.1 CAN卡寄存器讀寫函數(shù)

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

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

    {

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

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

    {

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

    }

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

    2.2 CAN卡初始化

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

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

    第二卡,設(shè)置CAN卡默認(rèn)參數(shù):

    CanCardConfigInfo CAN_DEFAULT_SETTING=

    {0X00,0XFF,0X03,0X1C};/*設(shè)置默認(rèn)波特率為125Kbps*/

    DWORD dwThreadID =0;

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

    第三卡,用WinCE API函數(shù)LocalAlloc為CAN卡驅(qū)動(dòng)中用到的數(shù)據(jù)結(jié)構(gòu)分配緩沖區(qū);通過HalTranslateBusAddress和MmMapIoSpace函數(shù)映射I/O地址,提供直接訪問設(shè)備的虛擬地址:

    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;

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

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

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

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

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

    2.3 CAN卡信息發(fā)送

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

    表1

    ID號(hào) 10 ID.10 ID.9 ID.8 ID.7 ID.6 ID.5 ID.4 ID.3
    RTR,數(shù)據(jù)長度碼 11 ID.2 ID.1 ID.0 RTR DLC.3 DLC.2 DLC.1 DLC.0
    數(shù)據(jù)1~8 12~19 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù)

    表2

    ID號(hào) 20 ID.10 ID.9 ID.8 ID.7 ID.6 ID.5 ID.4 ID.3
    RTR,數(shù)據(jù)長度碼 21 ID.2 ID.1 ID.0 RTR DLC.3 DLC.2 DLC.1 DLC.0
    數(shù)據(jù)1~8 22~29 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù) 數(shù)據(jù)

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

    BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)

    {

    BOOL bSuc=FALSE;

    ASSERT(hCan && lpMsg && lpMsg->dwMessageLen <=8); /*防錯(cuò)處理*/

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

    return FALSE;

    :: EnterCriticalSection(&hCan->lpCanHWInfo->

    TransmitCritSec); /*進(jìn)入臨界區(qū)*/

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

    CANW(hCan,10,byV); /*設(shè)置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);/*設(shè)置ID值低3位、RTR及數(shù)據(jù)長度*/

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

    {

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

    } /*采集數(shù)據(jù)*/

    CANW(hCan,1,1);/*重置傳輸請(qǐng)求*/

    while(TRUE)

    {byV=CANR(hCan,2);

    if(byV & 0X40) /*傳輸緩沖區(qū)滿,退出*/

    {break;}

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

    bSuc = TRUE;

    break;}

    }

    ::LeaveCriticalSection(&hCan->lpCanHWInfo->TransmitCritSec); /*離開臨界區(qū)*/

    return bSuc;

    }

    2.4 CAN卡信息接收

    CAN卡的信息接收是發(fā)送的逆過程,當(dāng)接收緩沖區(qū)標(biāo)志為1時(shí),表示緩沖區(qū)已滿可以接收數(shù)據(jù),將數(shù)據(jù)接收到數(shù)組后釋放接收緩沖區(qū),然后對(duì)接收到的數(shù)據(jù)進(jìn)行分解并存儲(chǔ)到CAN卡信息緩沖區(qū)的結(jié)構(gòu)體。接收緩沖區(qū)的寄存器結(jié)構(gòu)如表2所列。

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

    BOOL CAN_RecvRecvMessage(LPCAN_HW_OPEN_INFO

    HCan,OUT LPCanCardMessageBuflpMsg)

    {……

    if(CANR(hCan,2)&1){ /*判斷接收緩沖區(qū)是否已滿*/

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

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

    CANW(hCan,1,4); /*釋放接收緩沖區(qū)*/

    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; /*返回?cái)?shù)據(jù)長度*/

    ……

    }

    else

    {++hCan->lpCanHWInfo->dwErrorMsgCount;}/*沒有收到數(shù)據(jù),錯(cuò)誤計(jì)數(shù)加1*/

    ::LeaveCriticalSection(&hCan->lpCanHWInfo->

    ReceiveCritSec); /*離開臨界區(qū)*/

    Return bSuc;

    }

    2.5 CAN卡事件處理

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

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

    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線程已關(guān)閉則中斷*/

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

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

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

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

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

    } /*本次中斷結(jié)束,等待下次中斷*/

    return 0;

    }

    2.6 其它函數(shù)

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

    3 CAN卡驅(qū)動(dòng)封裝設(shè)計(jì)

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

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

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

    *CanRecvMsg;接收CAN卡數(shù)據(jù),打開CAN卡時(shí)必須具有GENERIC_READ權(quán)限。

    *CanSendMsg;通過CAN卡發(fā)送數(shù)據(jù)。打開CAN卡時(shí)必須具有GENERIC_WRITE權(quán)限。

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

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

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

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

    結(jié)語

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

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


    主站蜘蛛池模板: 欧美色图在线视频| 777米奇影视盒| 日韩在线观看中文字幕| 免费观看理论片毛片| 香蕉高清免费永久在线视频| 在线视频精品一区| 久久99精品久久只有精品| 最近免费中文字幕大全高清10| 免费观看美女用震蛋喷水的视频| 被黑人侵犯若妻中文字幕| 国内免费高清视频在线观看| 中文字幕曰产乱码| 日韩一级黄色影片| 亚洲欧美日韩综合在线播放| 男男动漫全程肉无删减有什么| 深夜放纵内射少妇| 国产精品午夜爆乳美女| 丝袜高跟美脚国产1区| 日本成人免费在线观看| 亚洲欧美国产中文| 特级无码a级毛片特黄| 国产一区二区不卡免费观在线| 高铁上要了很多次| 国产精品电影网| youjizz护士| 成人中文字幕在线| 久久精品亚洲欧美va| 校花小雪和门卫老头阅读合集| 国产精品成人99久久久久| 国产男女无遮挡猛进猛出| 国产a级黄色毛片| sihu永久在线播放地址| 美女胸又大又黄又www的网站| 极品少妇伦理一区二区| 成年女人毛片免费播放视频m| 亚洲日韩欧美一区二区三区在线| 狠狠色丁香婷婷综合潮喷| 国产69精品久久久久9999apgf | 国产成人一区二区三区免费视频| 99在线精品视频在线观看| 女人18毛片水最多|