柚子快報激活碼778899分享:單片機(jī) stm32 GPIO
柚子快報激活碼778899分享:單片機(jī) stm32 GPIO
文章目錄
一、GPIO_SetBits的作用二、詳細(xì)解析1.函數(shù)原型1.1.解析 GPIO_TypeDef* GPIOx1.2 解析 assert_param(IS_GPIO_ALL_PERIPH(GPIOx))1.3 解析 assert_param(IS_GPIO_PIN(GPIO_Pin))1.4 解析 GPIOx->BSRR = GPIO_Pin
一、GPIO_SetBits的作用
GPIO_SetBits函數(shù)用于將某位引腳置1,使其輸出高電平。
二、詳細(xì)解析
1.函數(shù)原型
代碼如下:
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
1.1.解析 GPIO_TypeDef* GPIOx
代碼如下:
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;
GPIO_TypeDef是一個結(jié)構(gòu)體變量,變量類型時結(jié)構(gòu)體。如同int變量的變量類型是整形變量。
GPIO_TypeDef* GPIOx 類似于 int* p; 表示一個結(jié)構(gòu)體變量的地址,前面定義這個類型的結(jié)構(gòu)體變量,給這個變量的各個成員賦予我們需要用到的值。最后通過它的地址找到這個結(jié)構(gòu)體變量,用這個結(jié)構(gòu)體變量成員的值初始化GPIOx 。
GPIO_TypeDef* GPIOx 類似于 int* p; p=&a; 所以p是一個地址值,那么GPIOx也表示一個地址值。GPIOx為GPIOA時就表示GPIOA的起始地址GPIOx為GPIOB時就表示GPIOA的起始地址。
由于GPIO_TypeDef結(jié)構(gòu)體變量里的成員變量的地址是連續(xù)的。所以GPIOx指向誰,地址就從誰開始。
1.2 解析 assert_param(IS_GPIO_ALL_PERIPH(GPIOx))
assert_param函數(shù)的作用就是檢測傳遞給函數(shù)的參數(shù)是否是有效的參數(shù)。其中assert_param的傳入?yún)?shù)是一個宏。
#define IS_GPIO_ALL_PERIPH(PERIPH) ( ((PERIPH) == GPIOA) || \
((PERIPH) == GPIOB) || \
((PERIPH) == GPIOC) || \
((PERIPH) == GPIOD) || \
((PERIPH) == GPIOE) || \
((PERIPH) == GPIOF) || \
((PERIPH) == GPIOG) )
IS_GPIO_ALL_PERIPH(PERIPH) 中的 PERIPH 和 PERIPH) == GPIOA 的 PERIPH 一樣,也就是說IS_GPIO_ALL_PERIPH(PERIPH)中的 PERIPH 只能為 GPIOA~G 這=中的其中一個。
1.3 解析 assert_param(IS_GPIO_PIN(GPIO_Pin))
#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) 1、 ((PIN) & (uint16_t)0x00) == 0x00 無論P(yáng)IN為何值其相與的結(jié)果都為0x00;也就是這個等式恒成立成立; 2、 (PIN) !=(uint16_t)0x00) 如果PIN=0x00;就不成立;其他的PIN值都成立; 1&&2 表示兩者都成立為真 否則為假;也就是PIN的值不能為0x00; 例如GPIO_SetBits(GPIOB,GPIO_Pin_5); 中的GPIO_Pin_5就不等于0x00,其值為0x20。且GPIO_Pin_0~GPIO_Pin_15的值都不為0x00
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */
1.4 解析 GPIOx->BSRR = GPIO_Pin
typedef struct
{
__IO uint32_t CRL; /*GPIO 端口配置低寄存器 地址偏移: 0x00 */
__IO uint32_t CRH; /*GPIO 端口配置高寄存器 地址偏移: 0x04 */
__IO uint32_t IDR; /*GPIO 數(shù)據(jù)輸入寄存器 地址偏移: 0x08 */
__IO uint32_t ODR; /*GPIO 數(shù)據(jù)輸出寄存器 地址偏移: 0x0C */
__IO uint32_t BSRR; /*GPIO 位設(shè)置/清除寄存器 地址偏移: 0x10 */
__IO uint32_t BRR; /*GPIO 端口位清除寄存器 地址偏移: 0x14 */
__IO uint32_t LCKR; /*GPIO 端口配置鎖定寄存器 地址偏移: 0x18 */
} GPIO_TypeDef;
BSRR寄存器被定義在 GPIO_TypeDef 結(jié)構(gòu)體里,GPIOx->BSRR 這一步已經(jīng)給出了IO口的具體地址,由于BSRR寄存器是32位的,詳情在下圖。 由上圖可以知道,BSRR寄存器高16位寫1->清0,低16位寫1->置1,由 #define GPIO_Pin_5 ((uint16_t)0x0020),0x0020化為二進(jìn)制數(shù)是 0000 0000 0010 0000,是低16位(全32位的二進(jìn)制數(shù)為:0000 0000 0000 0000 0000 0000 0010 0000),所以將0x20賦值給BSRR寄存器的話,就是在BSRR寄存器內(nèi)的第 6(5+1)個位 置1。
對 GPIOx->BSRR = GPIO_Pin 另一個通俗點(diǎn)的理解(和上面的理解有相似之處)就是: GPIOx->BSRR的意思就是告訴我們,置1或者置0,需要在BSRR寄存器里面設(shè)置,但是具體怎么設(shè)置呢? GPIO_Pin 就是具體的設(shè)置方法了。因?yàn)锽SRR寄存器是32位的(里面有32個位置可以置1或者置0),而 GPIO_Pin_5 的置為 0x0020,0x0020化為二進(jìn)制數(shù)是 0000 0000 0010 0000,是低16位(全32位的二進(jìn)制數(shù)為:0000 0000 0000 0000 0000 0000 0010 0000),所以將0x20賦值給BSRR寄存器的話,就是在BSRR寄存器內(nèi)的第 6(5+1)個位 置1。
GPIOx->BSRR = GPIO_Pin 還有一個理解。在使用例子 GPIO_SetBits(GPIOB,GPIO_Pin_5) 中,GPIOx->BSRR 的 GPIOx 為GPIOB,而:
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define PERIPH_BASE ((uint32_t)0x40000000)
所以,GPIOB的基地址是 0x40000000 + 0x10000 + 0x0C00 = 0x40010C00。整個GPIOB的地址范圍是一段內(nèi)存地址,。下面寄存器的地址分別為: 0x00 、 0x04 、 0x08 、 0x0C 、 0x10 、 0x14 、 0x18,每個相差 0x04 - 0x00 = 4 個內(nèi)存單元,所以最大的地址為0x18 + 4 = 0x1C,所以 GPIOB 他的地址范圍大小是0x00 ~ 0x1C (0x40010C00 ~ 0x40010C1C) 。
typedef struct
{
__IO uint32_t CRL; /*GPIO 端口配置低寄存器 地址偏移: 0x00 */
__IO uint32_t CRH; /*GPIO 端口配置高寄存器 地址偏移: 0x04 */
__IO uint32_t IDR; /*GPIO 數(shù)據(jù)輸入寄存器 地址偏移: 0x08 */
__IO uint32_t ODR; /*GPIO 數(shù)據(jù)輸出寄存器 地址偏移: 0x0C */
__IO uint32_t BSRR; /*GPIO 位設(shè)置/清除寄存器 地址偏移: 0x10 */
__IO uint32_t BRR; /*GPIO 端口位清除寄存器 地址偏移: 0x14 */
__IO uint32_t LCKR; /*GPIO 端口配置鎖定寄存器 地址偏移: 0x18 */
} GPIO_TypeDef;
柚子快報激活碼778899分享:單片機(jī) stm32 GPIO
參考閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。