新聞中心

        EEPW首頁 > 模擬技術 > 設計應用 > WINCE6.0 簡單LED驅動程序的編寫

        WINCE6.0 簡單LED驅動程序的編寫

        作者: 時間:2012-06-20 來源:網絡 收藏

        把它寫成了實驗報告的樣子! 在此BLOG中的有些函數是針對特定的BSP, 比如:地址的映射函數, 在每一個BSP中它的地址映射函數都不同, 但是都是地址映射(廢話當然是地址映射了)。其實里面有很多的東西都還可以添加:比如添加讀取信息狀態, 優化地址映射(不必把全部的GPIO都映射, 可以自定義一個小的結構體來實現)。
        一. 實驗目的
        a) 掌握流驅動的結構
        b) 掌握一般流驅動的編寫方法

        二. 實驗設備
        a) S3C6410 開發板一臺
        b) PC 機一臺, VS2005, CE 環境

        三. 實驗內容
        a) 進行簡單 驅動的編寫。

        四. 實驗原理
        a) 硬件原理圖
        i.
        ii.
        iii. 從原理圖可以知道如果我們要點亮 x , 只需要 GPMx 輸出高電平, 如果要熄滅 LEDx , 只需要 GPMx 輸出低電平即可。

        b) 軟件原理設計
        i. 由于在 中使用都是虛擬的地址, 所以需要將實際的物理地址轉換為虛擬地址來使用。 在系統提供的 BSP 中提供了一個函數來實現從物理地址到虛擬地址的映射。
        1. void *DrvLib_MapIoSpace (UINT32 PhysicalAddress , UINT32 NumberOfBytes , BOOL CacheEnable )
        2. 把物理地址轉換為虛擬地址。(其實它就是在地址映射表中查找相應的物理地址,然后返回對應的虛擬地址加上它的偏移。)
        3. UINT32 PhysicalAddress :要實現映射的物理地址的起始地址。
        4. UINT32 NumberOfBytes : 要映射物理地址的長度。
        5. BOOL CacheEnable :該物理地址是否使用了CACHE.( 具體參照地址映射表) 。
        ii. LED 上下文結構體的定義
        1. 定義了一個 LED 驅動的上下文, 用來保存 LED 驅動的信息。 但是只是簡單的 LED 驅動, 沒有包含多的數據。
        typedef struct
        {
        volatile S3C6410_GPIO_REG *pGPIOReg ;
        }LED_PUBLIC_CONTEXT , *PLED_PUBLIC_CONTEXT ;
        2 . S3C6410_GPIO_REG 是BSP 預先定義的一個GPIO 使用的數據結構。
        iii. GPIO 寄存器的使用。 GPIO 寄存器的地址都映射到了虛擬的地址上。 BSP 提供了一個結構體方便 GPIO 寄存器的使用。
        1. typedef struct
        { ……………..
        UINT32 GPMCON; // 820
        UINT32 GPMDAT; // 824
        UINT32 GPMPUD; // 828
        ………………..
        } S3C6410_GPIO_REG, *PS3C6410_GPIO_REG;
        2. 在使用這個結構全的時候把 GPIO 的虛擬地址的基地址映射到此結構的開始即可以操作此結構體的數據來操作實際的寄存器。
        3. 進行GPIO 物理地址到虛擬地址的映射: pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE ) ;
        iv. 實現 LED 燈狀態的操作。
        1. 獲得了 GPIO 的虛擬地址就可以像實際的物理地址那樣實現寄存器的操作。
        2.
        a) // 使能上拉
        b) pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
        c) // 設置為輸出
        d) pLedContext ->pGPIOReg ->GPMCON = 0x111111;
        e) // 關閉所有的LED
        f) LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
        3. 為了方便進行操作,定義了一組宏。
        // 打開或關閉LED0
        #define LED0_ON (x ) (x |= 0x00000001)
        #define LED0_OFF (x ) (x = 0xfffffffe)
        // 打開或關閉LED1
        #define LED1_ON (x ) (x |= 0x00000002)
        #define LED1_OFF (x ) (x = 0xfffffffd)
        // 打開或關閉LED2
        #define LED2_ON (x ) (x |= 0x00000004)
        #define LED2_OFF (x ) (x = 0xfffffffb)
        // 打開或關閉LED3
        #define LED3_ON (x ) (x |= 0x00000008)
        #define LED3_OFF (x ) (x = 0xfffffff7)
        // 打開或關閉所有的LED
        #define LED_ALL_ON (x ) (x |= 0x0000000f)
        #define LED_ALL_OFF (x ) (x = 0xfffffff0)
        五. 實驗步驟
        a) Xxx_Init 函數的原型:
        i. DWORD XXX_Init( LPCTSTR pContext , DWORD dwBusContext );
        ii. pContext: Pointer to a string containing the registry path to the active key for the stream interface driver.
        iii. lpvBusContext: Potentially process-mapped pointer passed as the fourth parameter to ActivateDeviceEx . If this driver was loaded through legacy mechanisms, then dwBusContext is zero. This pointer, if used, has only been mapped again as it passes through the protected server library (PSL). The XXX _Init function is responsible for performing all protection checking
        iv. 返回值 : Returns a handle to the device context created if successful. Returns zero if not successful. This handle is passed to the XXX_Open (Device Manager) , XXX_PowerDown (Device Manager) , XXX_PowerUp (Device Manager) , and XXX_Deinit (Device Manager) functions
        v. 注意:當調用 設備管理程序當調用 ActivateDeviceEx 函數的時候會間接調用到此函數, ActivateDeviceEx 的作用就是加載設備
        vi. LED_Init 函數的編寫。 LED_Init 最主要的功能就是進行硬件的初使化。
        vii. LED_Init 函數的實現:
        DWORD Led_Init (LPCTSTR pContext )
        {
        volatile PLED_PUBLIC_CONTEXT pLedContext ;

        RETAILMSG (DEBUG_LED ,(TEXT (Led_Init Function!/n )));

        // 申請LED 的CONTEXT
        pLedContext = (PLED_PUBLIC_CONTEXT )LocalAlloc (LPTR , sizeof (pContext ));
        if (!pLedContext )
        {
        RETAILMSG (DEBUG_LED , (TEXT (Can't alloc memory for led context!/n )));
        return NULL ;
        }

        // 得到GPIO 寄存器的地址
        pLedContext ->pGPIOReg = (volatile S3C6410_GPIO_REG *)DrvLib_MapIoSpace (S3C6410_BASE_REG_PA_GPIO , sizeof (S3C6410_GPIO_REG ), FALSE );
        if (pLedContext ->pGPIOReg == NULL )
        {
        RETAILMSG (DEBUG_LED , (TEXT (LED for pGPIORges: DrvLib_MapIoSpace failed!/n )));
        LocalFree (pLedContext );
        return NULL ;
        }

        // 使能上拉
        pLedContext ->pGPIOReg ->GPMPUD |= 0x0ff;
        // 設置為輸出
        pLedContext ->pGPIOReg ->GPMCON = 0x111111;
        // 關閉所有的LED
        LED_ALL_OFF (pLedContext ->pGPIOReg ->GPMDAT );
        RETAILMSG (DEBUG_LED , (TEXT (Led0 on! %d!/n ), (pLedContext ->pGPIOReg ->GPMDAT )));

        return pLedContext ;
        ` }
        a) Xxx_Write 函數原型:
        DWORD XXX_Write(DWORD
        hOpenContext
        , LPCVOID
        pBuffer
        , DWORD
        Count
        );

        本文引用地址:http://www.104case.com/article/186208.htm


        i. hOpenContext : Handle to the open context of the device. The call to the XXX_Open (Device Manager) function returns this identifier 。
        ii. pBuffer : Pointer to the buffer that contains the data to write.
        iii. Count: Number of bytes to write from the pBuffer buffer into the device.
        iv. 返回值: The number of bytes written indicates success. A value of –1 indicates failure.
        v. LED_Write 函數的作用只是進行對 LED 狀態的寫入。
        自定義結構體:
        typedef struct
        {
        unsigned char cLedNum ;
        unsigned char fLedStatue ;
        }LED_DATA , *PLED_DATA ;
        cLedNum :LED 的標號。0 對應第一個LED, 1 對應第2 個LED … 4 表示全部熄滅(因為它只有4 個LED )
        fLegStatue :將要實現的操作。 0 熄滅, 1 點亮。
        vi. LED_Write 函數的實現。
        DWORD Led_Write (DWORD hOpenContext ,
        DWORD pBuffer ,
        DWORD Count )
        {
        PLED_DATA pLedData = (PLED_DATA )pBuffer ;
        RETAILMSG (DEBUG_LED , (TEXT (Current hOpenContext %d /n )), hOpenContext );
        RETAILMSG (DEBUG_LED , (TEXT (Corrent GPMDATA %d!/n ), (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT )));

        switch (pLedData ->cLedNum )
        {
        case 0:
        if (pLedData ->fLedStatue )
        {
        LED0_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
        RETAILMSG (DEBUG_LED , (TEXT (Led0 on! %d/n! ), ((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT ));
        }
        else
        {
        LED0_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
        RETAILMSG (DEBUG_LED , (TEXT (Led0 off!/n! )));
        }
        break ;
        case 1:
        。。。。。。
        break ;
        case 2:
        。。。。。。
        break ;
        case 3:
        。。。。。。
        case 4:
        if (pLedData ->fLedStatue )
        { LED_ALL_ON (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
        }
        else
        { LED_ALL_OFF (((PLED_PUBLIC_CONTEXT )hOpenContext )->pGPIOReg ->GPMDAT );
        }
        default :
        break ;
        }

        return (Count );
        }

        b) 其它流接口函數的編寫:其它的流接口函數并沒有實現函數過程, 它們一般就直接返回。在Led_Deinit 函數中進行了申請內存的釋放,也調用了一個放棄映射的函數DrvLib_UnmapIoSpace , 其實這個函數在 之中沒有作用, 它是直接返回結果的函數。
        c) LED 的配置:
        設備管理器要使用LED 流驅動的接口,就必須將LED 提供的接口函數導出。在Led.def 文件中添加如下代碼:
        LIBRARY LED

        EXPORTS Led_Init
        Led_Deinit
        Led_Open
        Led_Close
        Led_Read
        Led_Write
        Led_Seek
        Led_PowerDown
        Led_PowerUp
        Led_IOControl

        導出了LED 的接口函數,要把Led.dll 添加到鏡像文件中去還要修改platform.bib 文件。

        在 MODULES 節中添加代碼如圖:


        最后修改注冊表 platform.reg :
        HKEY_LOCAL_MACHINE/Drives/BuildIn 下添加注冊表項 LED( 任意名字都可 )
        注冊表項中的內容:

        六. 實驗結果及分析
        a) 按照上述步驟進行 LED 流驅動的編寫, 再編寫一個簡單的應用程序即可進行 LED 燈的控制。



        關鍵詞: WINCE 6.0 LED 驅動程序

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 陇川县| 昭苏县| 广丰县| 双鸭山市| 疏附县| 丹棱县| 平定县| 林州市| 页游| 正定县| 嘉定区| 宿迁市| 科技| 河池市| 株洲县| 泰顺县| 永吉县| 彭泽县| 无极县| 吴堡县| 莱阳市| 漳州市| 天镇县| 晋宁县| 余江县| 泸西县| 樟树市| 西宁市| 诸城市| 都江堰市| 海阳市| 余庆县| 东乌珠穆沁旗| 会泽县| 赤城县| 达拉特旗| 赣州市| 临安市| 乾安县| 浙江省| 鄂尔多斯市|