5、認識庫函式
阿新 • • 發佈:2020-07-24
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;