圖爲 儲存器對應控制GPIO 以及時鐘外設等地址函數
編寫庫函數時 使用到了C語言的強制轉換,將指針指向向對應的GPIO外設和時鐘等地址,避免了相似寄存器學要多個定義每一個特有功能的寄存器。ui
比較以下:指針
庫函數原理
#ifndef stm32__H__
#define stm32__H__
#define PERIPH_BASE ((unsigned int)0x40000000) //stmf103外設總基地址
#define AHBPERIPH_BASE (PERIPH_BASE+0x20000)
#define APB1PERIPH_BASE (PERIPH_BASE)
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define RCC_BASE (AHBPERIPH_BASE+0x1000)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0c00)
#define uint_32t unsigned int
#define uint_16t unsigned short
#define uint_8t unsigned char
typedef struct{
uint_32t CRL;
uint_32t CRH;
uint_32t IDR;
uint_32t ODR;
uint_32t BSRR;
uint_32t BRR;
uint_32t LCKR;
}GPIO_Typedef;
typedef struct{
uint_32t RCC_CR;
uint_32t RCC_CFGR;
uint_32t RCC_CIR;
uint_32t RCC_APB2RSTR;
uint_32t RCC_APB1RSTR;
uint_32t RCC_AHBENR;
uint_32t RCC_APB2ENR;
uint_32t RCC_APB1ENR;
uint_32t RCC_BDCR;
uint_32t RCC_CSR;
uint_32t RCC_AHBRSTR;
}RCC_Typedef;im
#define GPIOB ((GPIO_Typedef*)(GPIOB_BASE))
#define RCC ((RCC_Typedef*)(RCC_BASE))img
#endif
語言
寄存器di
#ifndef STM32_H
#define STM32_H
#define PERIPH_BASE ((unsigned int)0x40000000)
#define APB1PERIPH PERIPH_BASE
#define AHBPERIPH_BASE (PERIPH_BASE+0x20000)
#define APB2PERIPH_BASE (PERIPH_BASE+0x10000)
#define RCC_BASE (AHBPERIPH_BASE+0x1000)
//基地址
#define GPIOA_BASE (APB2PERIPH_BASE+0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE+0x0c00)
#define GPIOC_BASE (APB2PERIPH_BASE+0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE+0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE+0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE+0x2c00)
#define GPIOG_BASE (APB2PERIPH_BASE+0x3000)工作
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)結構體
//低位寄存器
#define GPIOA_CRL *(unsigned int*)(GPIOA_BASE+0x00)
#define GPIOB_CRL *(unsigned int*)(GPIOB_BASE+0x00)
#define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00)
#define GPIOD_CRL *(unsigned int*)(GPIOD_BASE+0x00)
#define GPIOE_CRL *(unsigned int*)(GPIOE_BASE+0x00)
#define GPIOF_CRL *(unsigned int*)(GPIOF_BASE+0x00)
#define GPIOG_CRL *(unsigned int*)(GPIOG_BASE+0x00)
//高位寄存器
#define GPIOA_CRH *(unsigned int*)(GPIOA_BASE+0x04)
#define GPIOB_CRH *(unsigned int*)(GPIOB_BASE+0x04)
#define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04)
#define GPIOD_CRH *(unsigned int*)(GPIOD_BASE+0x04)
#define GPIOE_CRH *(unsigned int*)(GPIOE_BASE+0x04)
#define GPIOF_CRH *(unsigned int*)(GPIOF_BASE+0x04)
#define GPIOG_CRH *(unsigned int*)(GPIOG_BASE+0x04)
//輸出寄存器
#define GPIOA_ODR *(unsigned int*)(GPIOA_BASE+0x0c)
#define GPIOB_ODR *(unsigned int*)(GPIOB_BASE+0x0c)
#define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0c)
#define GPIOD_ODR *(unsigned int*)(GPIOD_BASE+0x0c)
#define GPIOE_ODR *(unsigned int*)(GPIOE_BASE+0x0c)
#define GPIOF_ODR *(unsigned int*)(GPIOF_BASE+0x0c)
#define GPIOG_ODR *(unsigned int*)(GPIOG_BASE+0x0c)
//輸入寄存器
#define GPIOA_IDR *(unsigned int*)(GPIOA_BASE+0x08)
#define GPIOB_IDR *(unsigned int*)(GPIOB_BASE+0x08)
#define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08)
#define GPIOD_IDR *(unsigned int*)(GPIOD_BASE+0x08)
#define GPIOE_IDR *(unsigned int*)(GPIOE_BASE+0x08)
#define GPIOF_IDR *(unsigned int*)(GPIOF_BASE+0x08)
#define GPIOG_IDR *(unsigned int*)(GPIOG_BASE+0x08)
//置位寄存器
#define GPIOA_BSRR *(unsigned int*)(GPIOA_BASE+0x10)
#define GPIOB_BSRR *(unsigned int*)(GPIOB_BASE+0x10)
#define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10)
#define GPIOD_BSRR *(unsigned int*)(GPIOD_BASE+0x10)
#define GPIOE_BSRR *(unsigned int*)(GPIOE_BASE+0x10)
#define GPIOF_BSRR *(unsigned int*)(GPIOF_BASE+0x10)
#define GPIOG_BSRR *(unsigned int*)(GPIOG_BASE+0x10)
//復位寄存器
#define GPIOA_BRR *(unsigned int*)(GPIOA_BASE+0x14)
#define GPIOB_BRR *(unsigned int*)(GPIOB_BASE+0x14)
#define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14)
#define GPIOD_BRR *(unsigned int*)(GPIOD_BASE+0x14)
#define GPIOE_BRR *(unsigned int*)(GPIOE_BASE+0x14)
#define GPIOF_BRR *(unsigned int*)(GPIOF_BASE+0x14)
#define GPIOG_BRR *(unsigned int*)(GPIOG_BASE+0x14)
#endif
進過比較會發現 每一個GPIO 都須要定義 指定的寄存器並且每一個都不同,可是當咱們用庫函數時會發現咱們的工做量少了,只須要把GPIO的基地址映射出來,而後在定義結構體 GPIO_Typdef ,在強制轉換爲GPIO_Typdef 。而後經過指針操做,相比之下工做輕鬆多了。
下面咱們來說他的原理 :
寄存器之間偏移地址爲0x04 (注意是十六進制,在編寫過程當中若是用十進制的話會訪問不到指定地址)
當我 們進行強轉時:
#define GPIOB ((GPIO_Typedef*)(GPIOB_BASE)) 至關於把 GPIOB_BASE 的地址 做爲 指針GPIOB的首地址
GPIOB_BASE 的地址是 :0x40010c00
寄存器
GPIOB_CRL 地址 GPIOB_BASE +偏移地址(0x00) 0x40010c00
GPIOB_CRH 地址 GPIOB_BASE +偏移地址(0x04) 0x40010c04
庫函數
結構體 GPIO_Typdef 結構 的成員均爲int_32T ,偏移地址爲4
當咱們 訪問 GPIOB ->CRL (首個成員就是結構體指針的地址) 那麼 地址爲:0x40010c00
訪問GPIOB->CRH 就是首個成員地址加上偏移地址 那麼 地址爲:0x40010c04
會發現本質就是地址的訪問