<strike id="kiyse"></strike>
  • <tr id="kiyse"></tr>
  • <strike id="kiyse"></strike><samp id="kiyse"><tbody id="kiyse"></tbody></samp>
    <strike id="kiyse"><s id="kiyse"></s></strike>
    <tr id="kiyse"></tr>
    <noframes id="kiyse"><code id="kiyse"></code></noframes>
    <th id="kiyse"></th>
    <samp id="kiyse"></samp>
  • <th id="kiyse"><s id="kiyse"></s></th>
  • 使用C#進(jìn)行CAN總線編程——基于WINCE平臺C#編程要點之三

     2008-8-28    

            英創(chuàng)ARM9系列嵌入式主板,如EM9000、EM9260均帶有(或可選)CAN總線接口,英創(chuàng)公司不僅提供了硬件平臺支持,還提供了CAN總線通訊驅(qū)動程序。本文主要介紹在基于Windows CE平臺的ARM9系列英創(chuàng)嵌入式主板下進(jìn)行C#(Microsoft Visual Stdio.Net 2005)CAN總線應(yīng)用程序開發(fā)時會常常用到的一些功能函數(shù)以及開發(fā)方法。

     

            在英創(chuàng)嵌入式主板上進(jìn)行CAN編程的思路是:

            (1)使用Win32的CreateFile方法(類似于傳統(tǒng)操作串口的模式)來獲得操作CAN總線端口的Handle。 


            (2)使用英創(chuàng)公司提供的CAN總線驅(qū)動程序動態(tài)鏈接庫CAN_API_DLL.dll實現(xiàn)一系列的CAN通訊操作,

            包括:CAN_StartChip、CAN_SetBaudRate、CAN_SetGlobalAcceptanceFilter、CAN_GetNextReceivedFrame、CAN_SendFrame、CAN_StartChip等方法。

            (3)使用Win32的CloseHandle方法關(guān)閉CAN操作的Handle。

            在使用C#編程操作CAN通訊之前,首先要明確:很多底層操作的函數(shù)(如CreateFile函數(shù)),Visual Studio 2005.NET的API庫中并沒有提供,這個時候,我們就要在C#開發(fā)中調(diào)用Win32的函數(shù)來進(jìn)行相應(yīng)的操作。一大批Win32底層操作的函數(shù)都存在于cordll.dll動態(tài)鏈接庫中。

            調(diào)用Win32的申明:

            using System.Runtime.InteropServices;

            要使用的兩個Win32函數(shù)申明如下:


    [DllImport(’coredll.dll’)]
    public static extern uint CreateFile(
    string FileName, //file name
    uint DesiredAccess, //access mode
    uint ShareMode, //share mode
    uint SecurityAttributes,// Security Attributes
    uint CreationDisposition, //how to create
    uint FlagsAndAttributes, //file attributes
    int hTemplateFile //handle to template file
    );
    [DllImport(’coredll.dll’)]
    static extern int CloseHandle(uint hDevice);

            同樣,英創(chuàng)公司提供的驅(qū)動程序動態(tài)鏈接庫函數(shù)也需要進(jìn)行申明如下:


    // 功能描述:讀取CAN設(shè)備接收數(shù)據(jù)包。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。
    // 輸出參數(shù)pRxFrameBuffer: 用于讀取CAN設(shè)備接收到的數(shù)據(jù)包。
    // 返回值= TRUE: 從CAN設(shè)備接收到數(shù)據(jù),并將接收到的數(shù)據(jù)包讀入pRxFrameBuffer。
    // = FALSE: CAN設(shè)備沒有接收數(shù)據(jù)。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_GetNextReceivedFrame@@YAHPAXPATMessageFrame@@@Z’)]
    public static extern bool CAN_GetNextReceivedFrame(uint hDevice, byte[] RxFrameBuffer );

    // 功能描述:通過CAN設(shè)備發(fā)送數(shù)據(jù)包。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。。
    // pTxFrameBuffer: 準(zhǔn)備通過CAN設(shè)備發(fā)送的數(shù)據(jù)包。
    // 返回值= TRUE: 從CAN設(shè)備發(fā)送數(shù)據(jù)成功。
    // = FALSE: 從CAN設(shè)備發(fā)送數(shù)據(jù)失敗。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_SendFrame@@YAHPAXPATMessageFrame@@@Z’)]
    //public static extern bool CAN_SendFrame(uint hDevice, MessageFrame[] TxFrameBuffer);
    public static extern bool CAN_SendFrame(uint hDevice, byte[] TxFrameBuffer);

    // 功能描述:設(shè)置CAN設(shè)備通訊的波特率。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。
    // Index=CAN_TIMING_10K : 10Kbps
    // CAN_TIMING_20K : 20Kbps
    // CAN_TIMING_50K : 50bps
    // CAN_TIMING_100K : 100bps
    // CAN_TIMING_125K : 125Kbps
    // CAN_TIMING_250K : 250Kbps
    // CAN_TIMING_500K : 500bps
    // CAN_TIMING_1000K: 1Mbps
    // 返回值= TRUE: 波特率設(shè)置成功。
    // = FALSE: 波特率設(shè)置失敗。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_SetBaudRate@@YAHPAXPAE@Z’)]
    public static extern bool CAN_SetBaudRate(uint hDevice, byte[] index);

    // 功能描述:設(shè)置CAN設(shè)備通訊接收過濾器配置。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。
    //AcceptanceFilter: 根據(jù)通訊報文格式定義過濾器的配置,定義為個字節(jié)的過濾器,其中前個字節(jié)用于定義過濾器的接收碼,
    // 后個字節(jié)用于定義過濾器的接收屏蔽碼,最后一個字節(jié)用于定義選擇單/雙濾波模式。
    // size: 定義的過濾器的大小。
    // 返回值= TRUE: 配置設(shè)置成功。
    // = FALSE: 配置設(shè)置失敗。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_SetGlobalAcceptanceFilter@@YAHPAXPAEE@Z’)]
    public static extern bool CAN_SetGlobalAcceptanceFilter(uint hDevice, byte[] AcceptanceFilter, byte size);

    // 功能描述:啟動CAN設(shè)備端口。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。
    // 返回值= NULL: 啟動CAN設(shè)備端口失敗。
    // != NULL: 啟動CAN設(shè)備端口返回的句柄。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_StartChip@@YAHPAX@Z’)]
    public static extern bool CAN_StartChip(uint hDevice);

    // 功能描述:停止CAN設(shè)備端口。
    // 輸入?yún)?shù)hDevice: 已創(chuàng)建CAN流式設(shè)備的句柄。
    // 返回值= TRUE: 停止CAN設(shè)備端口成功。
    // = FALSE: 停止CAN設(shè)備端口失敗。
    [DllImport(’CAN_API_DLL.dll’, EntryPoint = ’?CAN_StopChip@@YAHPAX@Z’)]
    public static extern bool CAN_StopChip(uint hDevice);

    一、啟動CAN接口

            啟動CAN接口一般只需要按順序進(jìn)行如下四個函數(shù)的調(diào)用:

    CANhandle = CreateFile(strPort, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); //注意:strPort是一個字符串,定義CAN端口的名稱,如“CAN1:”或“CAN2:”
    CAN_StartChip(CANhandle); //如下三個函數(shù)的定義請見上文注釋
    CAN_SetBaudRate(CANhandle, BaudrateSerialno);
    CAN_SetGlobalAcceptanceFilter(CANhandle, ACCFilter, 9);

            注意:ACCFilter是一個長度為9的字符串?dāng)?shù)組,請在調(diào)用之前安裝相關(guān)設(shè)置進(jìn)行初始化。

    二、數(shù)據(jù)發(fā)送

            啟動CAN接口后,就可進(jìn)行CAN通訊了。CAN的數(shù)據(jù)幀分標(biāo)準(zhǔn)幀和擴(kuò)展幀兩種,其區(qū)別如下圖所示:


            根據(jù)如上格式將發(fā)送的幀打包成byte數(shù)組后,即可通過如下函數(shù)進(jìn)行發(fā)送:

    bResult = CAN_SendFrame(CANhandle, TxBuf); //bResult是bool變量判斷發(fā)送成功與否,TxBuff就是打包后的幀byte數(shù)組。

    三、數(shù)據(jù)接收

            可以通過在程序里設(shè)置一個Timer或直接啟動一個線程來監(jiān)視是否有CAN數(shù)據(jù)幀發(fā)送進(jìn)來,并進(jìn)行接收。在Timer啟動的事件函數(shù)或線程函數(shù)中使用如下函數(shù)接收數(shù)據(jù):

    bResult = CAN_GetNextReceivedFrame(CANhandle, RxBuf); //bResult是bool變量判斷收到數(shù)據(jù)與否,TxBuff就是收到后的幀byte數(shù)組。

            需要注意的是函數(shù)CAN_GetNextReceivedFrame每執(zhí)行一次,只是讀取了一幀CAN數(shù)據(jù)報文,而收到的數(shù)據(jù)可能往往有不止一幀,客戶應(yīng)當(dāng)在應(yīng)用程序中將最新的數(shù)據(jù)全部讀出,這個時候需要反復(fù)調(diào)用該函數(shù),直到該函數(shù)的返回值為false。

            建議在接收幀的時候?qū)?shù)據(jù)先放到一個自定義的buffer中,然后在應(yīng)用程序的其它部分進(jìn)行處理,可以定義兩個全局變量:一個int類型存儲一次接收到幀的數(shù)量(如int mycount),一個較長的byte數(shù)組(或二維數(shù)組)作為自定義buffer存儲接收到的幀(如byte[,] myBuffer = new byte [20,13]。接收部分的示例代碼如下:

    byte[] RxBuf = new byte[13];
    byte dlen;
    bool bresult = true;
    mycount = 0;
    while (bresult)
    {
            bresult = CAN_GetNextReceivedFrame(CANhandle, RxBuf);
            if (bresult == false) return;
            for (int j = 0; j < 13; j++)
            {
                    myBuffer[mycount, j] = RxBuf[j];
            }
            Mycount ++;
    }

            收到數(shù)據(jù)后,可以通過判斷FrameInfo位的高位確定是標(biāo)準(zhǔn)幀還是擴(kuò)展幀,并獲得數(shù)據(jù)體的長度,進(jìn)而將數(shù)據(jù)分離出來進(jìn)行處理。

    四、關(guān)閉CAN接口

            關(guān)閉CAN接口一般只需要按順序進(jìn)行如下二個函數(shù)的調(diào)用即可實現(xiàn):

    CAN_StopChip(CANhandle);
    CloseHandle(CANhandle);

    在线精品自拍无码| 亚洲国产精品xo在线观看| 美女精品永久福利在线| 久久99热成人精品国产| 日本精品自产拍在线观看中文| 99在线视频精品| 中文字幕在线亚洲精品| 婷婷久久精品国产| 97色精品视频在线观看| 亚洲精品一卡2卡3卡三卡四卡| 国产精品9999久久久久| 久久996热精品xxxx| 国产精品乱子乱XXXX| 亚洲精品无码中文久久字幕| 日韩精品无码一区二区三区免费| 大陆精大陆国产国语精品| 合区精品久久久中文字幕一区| 麻豆国产精品一二三在线观看| 2021久久精品国产99国产精品| 久久精品人人槡人妻人人玩AV| 精品一区二区久久| 久久久久国产成人精品亚洲午夜| 无码精品人妻一区二区三区影院 | 精品无码AV一区二区三区不卡 | 国产精品福利在线| 久久99国产精品尤物| 亚洲国产精品无码久久久秋霞2| 成人精品视频一区二区三区 | 北岛玲在线精品视频| 日韩精品福利视频一区二区三区| 中文字幕久久久久久精品| 精品人妻系列无码一区二区三区| 99爱在线精品视频免费观看9| 久久亚洲AV无码精品色午夜麻| 国产精品免费高清在线观看| 国产在线精品无码二区| 999精品视频这里只有精品| 国内精品视频九九九九| 91视频国产精品| 亚洲一区二区三区在线观看精品中文| 国产成人综合日韩精品无码不卡|