新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > STM32外設庫文件分析(V3.5)

        STM32外設庫文件分析(V3.5)

        作者: 時間:2016-11-17 來源:網(wǎng)絡 收藏
        標準庫文件3.5版本
        1._htmresc 里面有兩個logo,沒用,刪除。
        2.Release_Notes.html 發(fā)行版本,可以看到各個版本的發(fā)行時間,修改內(nèi)容。
        3.Utilities 里面是一些測試C文件,評估使用。
        4.stm32f10x_stdperiph_lib_um.chm 幫助文件。
        5.Project 文件夾有個模版和一個例程。以工程模式提供。
        6.Libraries 文件夾下面包括兩個文件夾:
        CMSIS Cortex Microcontroller Software Interface Standard
        CM3
        CoreSupport:core_cm3.c core_cm3.h
        DeviceSupport
        ST
        STM32F10x:stm32f10x.h,system_stm32f10x.c,system_stm32f10x.h startup
        arm:啟動文件
        Documentation:Cortex Microcontroller Software Interface Standard 發(fā)行版本記錄
        STM32F10x_StdPeriph_Driver
        根據(jù)需要和開發(fā)環(huán)境對文件進行了一些精簡,精簡后的內(nèi)容:
        CMSIS Cortex Microcontroller Software Interface Standard
        CoreSupport
        Core_cm3.c:
        STM32從3.0庫開始引入了CMSIS,CMSIS是Cortex微控制器軟件接口標準(Cortex MicroController Software Interface Standard)的縮寫,
        這個是ARM定制的一個用于Cortex-M系列的一個標準,主要是為了提供通用api接口來訪問內(nèi)核和一些片上外設,提高代碼的可移植性。
        CMSIS有三個層:
        核內(nèi)外設訪問層 Core Peripheral Access Layer(CPAL),
        中間件訪問層 Middleware Access Layer(MWAL),
        設備訪問層 Device Peripheral Access Layer(DPAL)。
        CPAL用于訪問內(nèi)核的寄存器和組件,如NVIC,調(diào)試系統(tǒng)等。該層是由ARM實現(xiàn)的。
        MWAL用于對中間件的訪問,現(xiàn)在該層還未實現(xiàn)。(也不知道所謂的中間層是什么東西)。
        DPAL用于定義一些硬件寄存器的地址和一些外設訪問函數(shù),由芯片制造商實現(xiàn)。
        CPAL層的實現(xiàn)就是Core_cm3.c文件,DPAL層的實現(xiàn)就是system_stm32f10x.c文件(似乎還應該加上外設的函數(shù)庫)。
        接下來就來了解一下Core_cm3.c里面有什么東東:
        首先是匯編關鍵字__ASM和__INLINE的宏定義,支持不同的編譯器。由于使用的是Keil,所以就只看第一種,__CC_ARM。
        這里面的函數(shù)調(diào)用都只符合ARM過程調(diào)用標準的,如R0到R3用作參數(shù)和返回值傳遞,這也是這里面唯一用到的。
        此外,在Keil中使用了__asm關鍵字后,編譯器不會為函數(shù)增加返回指令,所以需要自己編寫返回命令,也就是每個函數(shù)后面的 bx lr。
        1. __ASM uint32_t __get_PSP(void):獲取進程堆棧指針PSP。
        2. __ASM void __set_PSP(uint32_t topOfProcStack):設置PSP。
        3. __ASM uint32_t __get_MSP(void):獲取主堆棧指針MSP。
        4. __ASM void __set_MSP(uint32_t mainStackPointer):設置MSP。
        5. __ASM uint32_t __REV16(uint16_t value):反轉半字中字節(jié)順序,如0xABCD反轉后得到0xCDAB。
        6. __ASM int32_t __REVSH(int16_t value):反轉字節(jié)順序,并做符號拓展。
        就是在__REV16函數(shù)得到的結果上再進行一次符號拓展。這兩個函數(shù)主要是方便進行大小端的切換。
        7. __ASM void __CLREX(void):清除由LDREX指令造成的互斥鎖。LDREX和STREX是Cortex用來實現(xiàn)互斥訪問,
        保護臨界資源的指令,LDREX執(zhí)行后,只有離它最近的一條存儲指令(STR,STREX)才能執(zhí)行,其他的存儲指令都會被駁回,
        而CLREX就是用于清除互斥訪問狀態(tài)的標記。
        8. __ASM uint32_t __get_BASEPRI(void):獲取BASEPRI寄存器的值,
        優(yōu)先級號高于該寄存器的中斷都會被屏蔽(優(yōu)先級號越大,優(yōu)先級越低),為零時不屏蔽任何中斷。
        9. __ASM void __set_BASEPRI(uint32_t basePri):設置BASEPRI的值。
        10. __ASM uint32_t __get_PRIMASK(void):PRIMASK是一個只有一位的寄存器,置位時屏蔽絕大部分的異常中斷,
        只剩下NMI和HardFault可以響應。
        11. __ASM void __set_PRIMASK(uint32_t priMask):設置PRIMASK的值。
        12. __ASM uint32_t __get_FAULTMASK(void):FAULTMASK也是一個只有一位的寄存器,為1時只有NMI才能響應,
        其他異常與中斷全部被屏蔽。
        13. __ASM void __set_FAULTMASK(uint32_t faultMask):設置FAULTMASK的值。
        14. __ASM uint32_t __get_CONTROL(void):獲取CONTROL的值。寄存器CONTROL只有兩位。
        CONTROL[0]選擇特權級別,0為特權級,1為敵用戶級。CONTROL[1]用于選擇堆棧指針,0為MSP,1為PSP。
        15. __ASM void __set_CONTROL(uint32_t control):設置CONTROL寄存器的值。
        BASEPRI,PRIMASK,F(xiàn)AULTMASK,CONTROL都只能在特權模式下被修改。
        C++的關鍵字 asm
        微軟詳述:
        __asm關鍵字啟動內(nèi)聯(lián)匯編并且能寫在任何c/c++合法語句之處.它不能單獨出現(xiàn).
        它必須接匯編指令、一組被大括號包含的指令或一對空括號.術語“__asm 塊”在這里是任意一個指令或一組指令無論是否在括號內(nèi)。
        以下代碼片段是在括號內(nèi)的一個簡單的__asm塊。
        __asm
        {
        mov al, 2
        mov dx, 0xD007
        out al, dx
        }
        另一種方法是,你可以在每個匯編指令前放置__asm
        __asm mov al, 2
        __asm mov dx, 0xD007
        __asm out al, dx
        因為__asm關鍵字是一個語句分隔符,你也可以將匯編指令放在同一行:
        __asm mov al, 2 __asm mov dx, 0xD007 __asm out al, dx
        以上三個的例子產(chǎn)生相同的代碼,但是第一種風格(把__asm塊用括號括起來)有一些優(yōu)勢。
        括號可以清晰的將C或C++代碼和匯編代碼分開,并且避免了不必要的重復__asm關鍵字。括號也能避免模糊性。
        如果你想在__asm塊的同一行放置一個C或C++語句,你必須將塊用括號括起來。
        沒有括號,編譯器不能告訴匯編代碼在哪里停止而C或C++代碼在哪里開始。
        最后,因為在括號的文字有和原始MASM一樣的格式,你能輕松的從一個已有的MASM源文件里剪切和黏貼文字到文件來。
        不同于C和C++的括號,包含__asm塊的括號對變量的作用域并沒有效果。你也能嵌套__asm塊,嵌套對變量作用域也沒有效果。
        core_cm3.h:里面包含了一些內(nèi)聯(lián)函數(shù),數(shù)據(jù)結構,這些數(shù)據(jù)結構都是核心的外設數(shù)據(jù)結構,大概包括:NVIC,SCB,ITM,CoreDebug,SysTick.
        對以上設備進行設置的函數(shù)也在這個頭文件里,以靜態(tài)內(nèi)聯(lián)函數(shù)的形式出現(xiàn),例如 static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn),
        其中,__INLINE 是__inline 的替代。 靜態(tài)函數(shù) static 聲明。
        Core_cm3.c 文件中定義的函數(shù)聲明也在這個文件中。
        invlude包含指令不僅僅限于.h頭文件,可以包含任何編譯器能識別的C/C++代碼文件,包括.c,.hpp,.cpp,.hxx,.cxx等,甚至.txt,.abc等等都可以。
           預處理器發(fā)現(xiàn) #include 指令后,就會尋找后跟的文件名并把這個文件的內(nèi)容包含到當前文件中。
        被包含文件中的文本將替換源代碼文件中的#include 指令,
        就像你把被包含文件中的全部內(nèi)容鍵入到源文件中的這個位置一樣。
        DeviceSupport
        stm32f10x.h:
        新版的固件庫V3.0以上 main等源文件中不再直接包含stm32f10x_conf.h,
        而是stm32f10x.h,stm32f10x.h則定義了啟動設置,以及所有寄存器宏定義,
        此文件中需要注意的有:
        1、device選擇
        #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD)
        && !defined (STM32F10X_MD_VL)&& !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL)
        && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
        /* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */
        /* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */
        /* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */
        /* #define STM32F10X_MD_VL */ /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */
        /* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */
        /* #define STM32F10X_HD_VL */ /*!< STM32F10X_HD_VL: STM32 High density value line devices */
        /* #define STM32F10X_XL */ /*!< STM32F10X_XL: STM32 XL-density devices */
        /* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */
        #endif
        #if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL)
        && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL)
        && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL)
        && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
        #error "Please select first the target STM32F10x device used in your application (in stm32f10x.h file)"
        #endif
        如果都沒有定義,編譯器會報錯。
        2、外設宏定義USE_STDPERIPH_DRIVER
        #if !defined USE_STDPERIPH_DRIVER
        #endif
        注意stm32f10x.h文件的后面有這樣的代碼,大概8300行左右:
        #ifdef USE_STDPERIPH_DRIVER
        #include "stm32f10x_conf.h"
        #endif
        stm32f10x_conf.h中包含了所有外設的頭文件,因此任意源文件只要包含了stm32f10x.h,就可以在源文件調(diào)用任意外設的函數(shù)。
        3、外部時鐘頻率選擇
        #if !defined HSE_VALUE
        #ifdef STM32F10X_CL
        #define HSE_VALUE ((uint32_t)25000000)
        #else
        #define HSE_VALUE ((uint32_t)8000000)
        #endif
        #endif
        注意STM32F10X_CL,STM32F10X_CL是stm32f105 和stm32f107 互聯(lián)型的device,
        用到此器件外部要選用25MHz的晶體,此處默認的外部8MHz的晶體
        4.stm32f10x.h包含了這些頭文件,include"stm32f10x.h",就不用包含下面這些了。
        #include "core_cm3.h"
        #include "system_stm32f10x.h"
        #include
        system_stm32f10x.c:
        這個文件中包含系統(tǒng)上電復位之后時鐘設置要調(diào)用的函數(shù):
        SystemInit()系統(tǒng)初始化,系統(tǒng)上電復位,main()在啟動其它分支程序以前調(diào)用的函數(shù)。
        SetSysClock(),被SystemInit()函數(shù)調(diào)用,設置系統(tǒng)時鐘頻率,根據(jù)宏定義選擇系統(tǒng)運行的時鐘頻率。
        SetSysClockTo24
        SetSysClockTo36
        SetSysClockTo48
        SetSysClockTo56
        SetSysClockTo72
        SetSysClockToHSE
        system_stm32f10x.h 源文件函數(shù)聲明的頭文件。
        startup文件夾包含各個系列的啟動代碼,用戶應該根據(jù)自己的芯片類型來選擇啟動代碼。
        STM32F10x_StdPeriph_Driver
        inc:頭文件沒什么好說的了,一個頭文件對用一個源文件,包括函數(shù),數(shù)據(jù)結構的的一些聲明
        src:這一層就是Device Peripheral Access Layer(DPAL)了,看看名字就知道是關于哪個設備的,沒什么
        說的。唯一有一個例外就是misc.c文件,STM32 V3.5版本的庫函數(shù)中沒有原來版本中單獨對于NVIC(中斷向量嵌套)的外設驅動,
        把NVIC的外設驅動放在了misc.c中,實際上是代替原來的stm32f10x_nvic.c.
        3.5 版本的庫文件中少了stm32f10x_it.c文件,需要自己添加。


        評論


        技術專區(qū)

        關閉
        主站蜘蛛池模板: 驻马店市| 社旗县| 兴国县| 景宁| 库车县| 汕尾市| 宜阳县| 姜堰市| 治多县| 盘山县| 浦县| 张掖市| 嘉鱼县| 台中市| 静安区| 寿光市| 三台县| 张掖市| 民勤县| 嘉禾县| 泰宁县| 肇东市| 白山市| 巴彦淖尔市| 正宁县| 黔江区| 泉州市| 河北区| 开平市| 尼木县| 潮州市| 抚顺市| 宕昌县| 南漳县| 鄂温| 镇江市| 荆州市| 中江县| 海原县| 海宁市| 盐津县|