1. 程式人生 > 實用技巧 >5、認識庫函式

5、認識庫函式

STM32庫函式

一、什麼是庫函式

​ 庫函式其實就是韌體的API (Application Program Interface),呼叫這些函式介面就可以很方便的配置STM32的暫存器,使開發人員可以脫離最底層的暫存器操作,簡化開發。

二、採取什麼方法

​ 主要用的方法就是進行暫存器對映,通過巨集定義、結構體、列舉的方式完成對底層程式碼的封裝。同時暫存器內的每一種暫存器地址是16個口連著的,因此不同的設定卻被分在了不同的暫存器上,這樣子在配置的時候就比較麻煩,所以庫函式封裝了之後可以將1個口的多個設定連著設定。

​ 之後為將這些基本的配置實現,就會寫一些函式,將設定好的資訊寫入微控制器記憶體裡。

三、C語言對暫存器的封裝

以GPIO口的暫存器為例

1、封裝匯流排和外設基地址

用巨集定義對外設和匯流排的基地址進行取別名,如下

/* 外設基地址 Block2 */ 
#define PERIPH_BASE			  ((unsigned int)0x40000000) 
    
/* 匯流排基地址 */ 
#define APB1PERIPH_BASE        PERIPH_BASE 
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000) 
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x00020000) 
    
/* GPIO 外設基地址 */ 
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800) 
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00) 

2、封裝暫存器列表

如果用上述辦法定義每一個GPIO的暫存器的話略顯繁瑣,因為每一個GPIO口都是有著一組相同功能的暫存器的。為了更方便的訪問不同GPIO的暫存器,可以用C語言中結構體的語法對暫存器進行封裝。

為何用結構體?

結構體可以用來對一段連續地址進行訪問,正好可以用來訪問一段連著的暫存器地址。

如下:

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 資料輸入暫存器      地址偏移: 0x08 */ 
    uint32_t ODR;     /*GPIO 資料輸出暫存器      地址偏移: 0x0C */ 
    uint32_t BSRR;    /*GPIO 位設定/清除暫存器   地址偏移: 0x10 */ 
    uint32_t BRR;     /*GPIO 埠位清除暫存器     地址偏移: 0x14 */ 
    uint16_t LCKR;    /*GPIO 埠配置鎖定暫存器   地址偏移: 0x18 */ 
} GPIO_TypeDef;  

之後便可以通過結構體訪問暫存器了,如下:

GPIO_TypeDef * GPIOx;      //定義一個 GPIO_TypeDef 型結構體指標 GPIOx 
GPIOx = GPIOB_BASE;        //把指標地址設定為巨集 GPIOH_BASE 地址 
GPIOx->IDR = 0xFFFF;        
GPIOx->ODR = 0xFFFF;        
   
uint32_t temp; 
temp = GPIOx->IDR;          //讀取 GPIOB_IDR 暫存器的值到變數 temp 中 

3、修改暫存器的位操作方法

如果只希望修改某長串地址中的某一位的話可以通過如下的方式:

置1
unsigned char a = 0x02;
//a = 0000 0010
//現在希望將a的最高位置1
a |= (1<<7);//將1左移7位,然後進行或賦值
置0
unsigned char a = 0x02;
//a = 0000 0010
//現在希望將a的第2位置0
a &= ~(1<<1);//將1左移1位,取反,然後進行與賦值
取反
unsigned char a = 0x02;
//a = 0000 0010
//現在希望將a的第2位取反
a ^= (1<<1);//將1左移1位,然後進行取反賦值

如果想操作很多位的話可以如下:

unsigned char a = 0x02;
//a = 0000 0010
//現在希望將a改為0x32
a |= 0x30;