国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

ludi的個(gè)人空間 http://m.qingdxww.cn/space-uid-138953.html [收藏] [復(fù)制] [RSS]

博客

STM32入門系列-使用C語言封裝寄存器

已有 1594 次閱讀2017-11-24 10:07 |個(gè)人分類:c語言

前面介紹了存儲器映射、寄存器和寄存器映射,這些都是為了介紹使用 C語言封裝寄存器做鋪墊。這里我們通過一個(gè)實(shí)例來對 C 語言封裝寄存器進(jìn)行介紹。

    具體實(shí)例:控制 GPIOC 端口的第 0 管腳輸出一個(gè)低電平。首先我們需要知道GPIOC 端口外設(shè)是掛接在哪個(gè)總線上的,然后根據(jù)總線基地址和本身的偏移地址得到 GPIOC 外設(shè)基地址,最后通過這個(gè)外設(shè)基地址得到里面各種寄存器基地址。

總線和外設(shè)基地址封裝

    根據(jù)寄存器的概念,我們可以使用 C 語言中的宏定義對寄存器進(jìn)行定義。具體代碼如下:

    //定義外設(shè)基地址

    #define PERIPH_BASE ((unsigned int)0x40000000) 1)

    //定義 APB2 總線基地址

    #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) 2)

    //定義 GPIOC 外設(shè)基地址

    #define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800) 3)

    //定義寄存器基地址 這里以 GPIOC 為例

    #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) 4)

    #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04)

    #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08)

    #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C)

    #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10)

    #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14)

    #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18)

    上述代碼中我們在后面?zhèn)渥⒘藬?shù)字,下面對其進(jìn)行簡單介紹下其功能:

· 

定義外設(shè)的基地址,這個(gè)地址也是 Block2 的基地址。

· 

· 

定義 APB2 總線基地址,因?yàn)?Block2 的第一個(gè)總線是 APB1,而 APB2 總線地址只需要加上對應(yīng)的地址偏移量即可。

· 

· 

定義 GPIO 外設(shè)基地址,因?yàn)?GPIOC 是掛接在 APB2 總線上的,所以找到對應(yīng)的端口地址偏移量即可知道 GPIOC 端口基地址。

· 

· 

定義 GPIO 外設(shè)寄存器基地址,這里以 GPIOC 端口為例,因GPIOC_CRL是 GPIOC 外設(shè)的第一個(gè)寄存器,所以基地址就是 GPIOC 地址,其他寄存器地址只需要在 GPIOC 基地址上加上相應(yīng)的偏移量即可。

· 

    我們得到了寄存器具體的地址,那么就可以使用 C 語言指針來操作讀寫。例如我們需要 GPIOC0 輸出一個(gè)低電平或者高電平,可以使用下面語句來操作。

    //控制 GPIOC 第 0 管腳輸出一個(gè)低電平

    GPIOC_BSRR = (0x01<<(16+0));

    //控制 GPIOC 第 0 管腳輸出一個(gè)高電平

    GPIOC_BSRR = (0x01<<0);

    我們知道 GPIOC_BSRR 的值是這個(gè)寄存器的地址,但是編譯器不知道它是地址,而是把它當(dāng)做立即數(shù),所以我們必須要強(qiáng)制轉(zhuǎn)換為(unsigned int *)指針類型才可以對其操作,這一點(diǎn)特別要注意。嵌入式物聯(lián)網(wǎng)智能硬件等系統(tǒng)學(xué)習(xí)企鵝意義氣嗚嗚吧久零就易,然后再在前面加上一個(gè)“*”作取指針操作,表示對該地址內(nèi)內(nèi)容進(jìn)行寫,讀操作也同樣使用“*”取指針操作。如下:

    unsigned int temp;

    temp =GPIOC_IDR;

    將寄存器內(nèi)的數(shù)據(jù)保存在變量 temp 中,使用到變量時(shí)一定要進(jìn)行定義。

寄存器封裝

    通過前面講解,我們已經(jīng)可以對寄存器進(jìn)行操作,但是還稍有不足,因?yàn)镾TM32的GPIO比較多, 我們不可能每使用一個(gè)GPIO都做前面一樣的一大堆定義。根據(jù)GPIO寄存器的特點(diǎn),我們知道不論GPIOA還是GPIOB等都擁有一組功能相同的寄存器,如GPIOA_ODR/GPIOB_ODR/GPIOC_ODR等等,它們只是地址不一樣。

    為了更方便地訪問寄存器,我們引入C語言中的結(jié)構(gòu)體對寄存器進(jìn)行封裝,具體代碼如下:

    typedef unsigned int uint32_t; /*無符號 32 位變量*/

    typedef unsigned short int uint16_t; /*無符號 16 位變量*/

    /* GPIO 寄存器列表 */

    typedef struct

    {

        uint32_t CRL; /*GPIO 端口配置低寄存器 地址偏移: 0x00 */

        uint32_t CRH; /*GPIO 端口配置高寄存器 地址偏移: 0x04 */

        uint32_t IDR; /*GPIO 數(shù)據(jù)輸入寄存器 地址偏移: 0x08 */

        uint32_t ODR; /*GPIO 數(shù)據(jù)輸出寄存器 地址偏移: 0x0C */

        uint32_t BSRR; /*GPIO 位設(shè)置/清除寄存器 地址偏移: 0x10 */

        uint32_t BRR; /*GPIO 端口位清除寄存器 地址偏移: 0x14 */

        uint16_t LCKR; /*GPIO 端口配置鎖定寄存器 地址偏移: 0x18 */

    }GPIO_TypeDef;

    這段代碼用 typedef 關(guān)鍵字聲明了名為GPIO_TypeDef的結(jié)構(gòu)體類型,結(jié)構(gòu)體內(nèi)有7 個(gè)成員變量,變量名正好對應(yīng)寄存器的名字。C 語言的語法規(guī)定,結(jié)構(gòu)體內(nèi)變量的存儲空間是連續(xù)的,其中32位的變量占用4個(gè)字節(jié),16 位的變量占用2個(gè)字節(jié)。

    于是,我們定義的GPIO_TypeDef,假如這個(gè)結(jié)構(gòu)體的首地址為0x4001 1000(這也是第一個(gè)成員變量 CRL的地址),那么結(jié)構(gòu)體中第二個(gè)成員變量CRH的地址即為0x4001 1000 +0x04,加上的這個(gè)0x04,正是代表CRH所占用的4個(gè)字節(jié)地址的偏移量,其它成員變量相對于結(jié)構(gòu)體首地址的偏移,在上述代碼右側(cè)注釋已給出。

    這樣的地址偏移與STM32 GPIO外設(shè)定義的寄存器地址偏移一一對應(yīng),只要給結(jié)構(gòu)體設(shè)置好首地址,就能把結(jié)構(gòu)體內(nèi)成員的地址確定下來,然后就能以結(jié)構(gòu)體的形式訪問寄存器了,比如我們還是將GPIOC0輸出低電平,具體代碼如下:

    GPIO_TypeDef * GPIOx; //定義一個(gè)GPIO_TypeDef型結(jié)構(gòu)體指針GPIOx

    GPIOx = GPIOC_BASE; //把指針地址設(shè)置為宏 GPIOC_BASE 地址

    GPIOx->BSRR =(1<<(16+0)); //通過指針訪問并修改 GPIOC_BSRR 寄存器

    這段代碼先用GPIO_TypeDef類型定義一個(gè)結(jié)構(gòu)體指針GPIOx,并讓指針指向GPIOC基地址GPIOC_BASE,地址確定下來,然后根據(jù)C語言訪問結(jié)構(gòu)體的內(nèi)容,用GPIOx->BSRR寫寄存器。為了操作更簡便靈活,我們直接使用宏定義好GPIO_TypeDef類型的指針,而且指針指向各個(gè)GPIO端口的首地址,使用時(shí)我們直接用該宏訪問寄存器即可。具體代碼如下:

    #define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

    #define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)

    #define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

    #define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)

    #define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)

    #define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)

    #define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)

    GPIOC->BSRR = (1<<(16+0));

    我們這里僅僅以GPIO這個(gè)外設(shè)為例,給大家講解了如何使用C語言對寄存器封裝,對于其他的外設(shè)也是使用同樣方法。其實(shí)到了后面的實(shí)驗(yàn)程序的編寫,我們都是使用ST公司提供的固件庫,他們把STM32所有外設(shè)都已經(jīng)封裝好了,我們只需要調(diào)用即可。 我們這里分析這個(gè)封裝過程只是想讓大家更加清楚理解如何使用C來封裝寄存器的。

 


路過

雞蛋

鮮花

握手

雷人

評論 (0 個(gè)評論)

facelist

您需要登錄后才可以評論 登錄 | 立即注冊

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
返回頂部
主站蜘蛛池模板: 欧美黑寡妇香蕉视频 | 国产成人99精品免费观看 | 欧美日韩一区二区三区视频播 | 国产护士资源总站 | 欧美日韩在线精品一区二区三区 | 欧美日韩一区二区不卡三区 | 999人在线精品播放视频 | 天堂亚洲国产日韩在线看 | 四虎影视大全 | www.亚洲天堂| 亚洲爱爱视频 | 四虎在线免费视频 | 亚洲国产欧美在线不卡中文 | 婷婷看片| 欧美精品无播放器在线观看 | 免费黄址 | 久久99精品国产麻豆宅宅 | 四虎影视色费永久在线观看 | aaa在线视频 | 国产精品动漫网站 | 在线免费黄| 三级网站片| 麻豆视频国产 | 国产精品资源网 | 亚洲综合婷婷 | 18到20岁女人一级毛片 | 韩国av片永久免费 | 唯美久草 | 精品国产国产综合精品 | 78视频在线观看免费播放 | 91亚洲精品视频 | 免费国产成高清人在线视频 | 干干干操操操 | 亚洲免费视频网址 | 欧美不卡视频 | 把女人弄爽特黄a大片片 | 日本韩国免费 | 久久久国产一区二区三区丝袜 | 久久久亚洲天堂 | 一区二区三区视频观看 | 久久青草国产手机看片福利盒子 |