STM32的固件庫文件功能相當完善,提供的API完全能滿足一般的項目需要。剛從51單片機轉到STM32的人,肯定會被這么龐大的東東嚇到,51單片機上對IO口操作,簡簡單單幾行代碼就搞定了,一個C源文件就搞定。假如用STM32,對IO口進行簡單操作,遠不是幾行代碼能搞定的。(其實直接操作寄存器也能搞定)。
廢話不多說,這就帶你解剖固件庫文件,包你看完之后豁然開朗。
首先,請看一段簡單的C語言代碼
#include <stdio.h>
#define base 0x0012ff60
#define flash ((TestType *)base)
typedef struct
{
int i;
int j;
int k;
}TestType;
void main()
{
flash->i = 0;
flash->j = 1;
flash->k = 2;
printf( "%x \n", flash->i);
printf( "%x", &(flash->i));
}
有人會問了這段代碼有什么用?我告訴你ST的固件庫都是按照這種方式編寫的
上面程序打印出來結果為 0
0x0012ff60
把上面的程序分析幾分鍾后,我再給你揭曉。就拿GPIOA口來說吧,你看stm32f10x.h中能看到
#define PERIPH_BASE ((uint32_t)0x40000000)
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
小學學的加減法就能把GPIOA_BASE 算出來,為什么是這么多呢?看ST的手冊,人家就是要規定這樣,沒辦法。
有了地址之后,GPIOA的各個寄存器怎么辦涅,它們是控制IO的關鍵所在。GPIO的各個寄存器都是連續排列的,為什么要連續排呢,方便找啊,用結構體就能很好搞定了
在stm32f10x.h中
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
每個寄存器都是32位的,所以很方便用結構體尋找每個寄存器,准備工作都做好了,接下來就要開始針對GPIOA設置了
在core_cm3.c中
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
把地址強制轉換成結構體指針,這樣就能很方便對寄存器操作。
寄存器搞定了,接下來就真對用戶操作了,要很好的讓用戶使用,就得人性話點,所以用enum枚舉變量就能實現,你就再也不用為想輸入的值去煩惱了,直接輸入名稱就行了,拿IO口的輸出速度來說
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
要說人性化,ST還有一點不得不提,那就是位帶操作,改變了 寫地址-取地址數據-位操作-數據寫入地址的操作,直接改為寫地址-數據寫入
,直接位操作。
ST的編程結構是很值得借鑒的,使得編程序時結構很清晰,脈絡很清楚。至於如何去發揮,得看個人水平了