STM32小筆記(一) GPIO口的配置
GPIO口的使用:
1.GPIO和AFIO 全系列支持
GPIO寄存器
(1)兩個(gè)32位配置寄存器(GPIOx_CRL,GPIOx_CRH);
(2)兩個(gè)32位數(shù)據(jù)寄存器(GPIOx_IDR,GPIOx_ODR);
(3)一個(gè)32位置為/復(fù)位寄存器(GPIOx_BSRR);
(4)一個(gè)16位復(fù)位寄存器(GPIOx_BRR);
(5)一個(gè)32位鎖存器(GPIOx_LCKR);
輸入配置
當(dāng)I/O端口配置為輸入時(shí):
● 輸出緩沖器被禁止
● 施密特觸發(fā)輸入被激活
● 根據(jù)輸入配置(上拉,下拉或浮動(dòng))的不同,弱上拉和下拉電阻被連接
● 出現(xiàn)在I/O腳上的數(shù)據(jù)在每個(gè)APB2時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器
● 對(duì)輸入數(shù)據(jù)寄存器的讀訪問(wèn)可得到I/O狀態(tài)
輸出配置
當(dāng)I/O端口被配置為輸出時(shí):
● 輸出緩沖器被激活
─ 開漏模式:輸出寄存器上的’0’激活N-MOS,而輸出寄存器上的’1’將端口置于高阻狀態(tài)(PMOS從不被激活)。
─ 推挽模式:輸出寄存器上的’0’激活N-MOS,而輸出寄存器上的’1’將激活P-MOS。
● 施密特觸發(fā)輸入被激活
● 弱上拉和下拉電阻被禁止
● 出現(xiàn)在I/O腳上的數(shù)據(jù)在每個(gè)APB2時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器
● 在開漏模式時(shí),對(duì)輸入數(shù)據(jù)寄存器的讀訪問(wèn)可得到I/O狀態(tài)
● 在推挽式模式時(shí),對(duì)輸出數(shù)據(jù)寄存器的讀訪問(wèn)得到最后一次寫的值。
STM32中的配置寄存器在固件函數(shù)庫(kù)中早已生成,因此無(wú)需再對(duì)寄存器的每個(gè)設(shè)定寫定義,而是直接調(diào)用關(guān)鍵字。這樣我們可以不再關(guān)心寄存器的具體配置(因?yàn)槟且呀?jīng)在固件配置好了);因此直觀的從配置函數(shù)中去看,更能有效的提高。
GPIO相關(guān)的庫(kù)函數(shù)如下,位于在“stm32f10x_gpio.h”
GPIO相關(guān)函數(shù)如下:
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
以下將逐個(gè)說(shuō)明函數(shù)功能及注釋說(shuō)明:
·void GPIO_DeInit(GPIO_TypeDef* GPIOx);
該函數(shù)原型在"stm32f10x_gpio.C"當(dāng)中,類似C++ 的注釋說(shuō)明如下:
* @brief Deinitializes the GPIOx peripheral registers to their default reset values.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval None
其中是為不同組的IO口進(jìn)行寄存器值的初始化。
初始化語(yǔ)句如下:
“ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);”
再追根溯源到這個(gè)函數(shù),位于“stm32f10x_rcc.C”當(dāng)中
"void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)"
{
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2RSTR |= RCC_APB2Periph;
}
else
{
RCC->APB2RSTR &= ~RCC_APB2Periph;
}
}
函數(shù)注釋如下:
一目了然,即配置IO口時(shí)鐘狀態(tài)為使能或者失效。
當(dāng)然在其中此函數(shù)作為一個(gè)初學(xué)實(shí)例還是值得深究的:
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
此處兩句即類似于C++中的斷言函數(shù),作為函數(shù)運(yùn)行的先決條件。這里將斷言函數(shù)直接說(shuō)明,在后續(xù)的實(shí)例中,仍舊會(huì)有使用到的地方。
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif
#endif
若滿足斷言值為"1"的條件,否則判定失敗輸出 文件名和所在行。不為"0"返回0.
再返回“assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));”此句中。“IS_RCC_APB2_PERIPH”如下定義:
·#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))
此處使用到的是AP2 進(jìn)入該函數(shù)還可以看到AP2、AP1、AP三個(gè)高速時(shí)鐘族的各項(xiàng)定義。姑且在這里認(rèn)為是判定開啟對(duì)應(yīng)時(shí)鐘前的時(shí)鐘功能驗(yàn)證。
·#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
只為考慮還是的形參是否是“DISABLE”or“ENABLE” 兩個(gè)狀態(tài)。
“ if (NewState != DISABLE)
{
RCC->APB2RSTR |= RCC_APB2Periph;
}
else
{
RCC->APB2RSTR &= ~RCC_APB2Periph;
}
”
而APB2RSTR則即將牽扯到RCC的設(shè)置問(wèn)題,我們下一節(jié)再講。
·void GPIO_AFIODeInit(void);功能復(fù)用,重新映射事件控制。
同樣調(diào)用“RCC_APB2PeriphResetCmd”。也是串口初始化判斷
·void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
寄存器手冊(cè)中記為:根據(jù)GPIO_InitStruct中指定參數(shù)初始化外設(shè)GPIOx寄存器
不想在此處在贅述此函數(shù),主要通過(guò)寫寄存器的值來(lái)配置GPI0x,GPIO_pin,GPIO_Mode,GPIO_speed,以及寫GPIO CRL/CRH寄存器。
·void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);被上一結(jié)構(gòu)體調(diào)用
GPIO_Speed 描述
GPIO_Speed_10MHz 最高輸出速率10MHz
GPIO_Speed_2MHz 最高輸出速率2MHz
GPIO_Speed_50MHz 最高輸出速率50MHz
GPIO_Mode_AIN 模擬輸入
GPIO_Mode_IN_FLOATING 浮空輸入
GPIO_Mode_IPD 下拉輸入
GPIO_Mode_IPU 上拉輸入
GPIO_Mode_Out_OD 開漏輸出
GPIO_Mode_Out_PP 推挽輸出
GPIO_Mode_AF_OD 復(fù)用開漏輸出
GPIO_Mode_AF_PP 復(fù)用推挽輸出
·
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);,
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
讀取指定管腳輸入/輸出,讀取管腳輸入/輸出數(shù)據(jù)值。 一個(gè)讀取的是管腳的狀態(tài),而一個(gè)讀取的輸入or 輸出數(shù)據(jù)寄存器的值。這一點(diǎn)要分清
·
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
"bitval must be Bit_RESET or Bit_SET“
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
“Portval為將寫入數(shù)據(jù)寄存器的值”
設(shè)定/清除指定的數(shù)據(jù)位
·void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
鎖存管腳寄存器,鎖存指定GPIO組指定引腳。
·void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
配置GPIO為事件輸出,其后我們來(lái)解決這個(gè)疑問(wèn)。
·void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
此函數(shù)決定了IO口的重新映射,實(shí)際是IO復(fù)用功能的實(shí)現(xiàn),GPIO_Remap選擇輸入引腳,NewState的配置值如下:GPIO_Remap_SPI1 SPI1復(fù)用功能映射
GPIO_Remap_I2C1 I2C1復(fù)用功能映射
GPIO_Remap_USART1 USART1復(fù)用功能映射
GPIO_PartialRemap_USART3 USART2復(fù)用功能映射
GPIO_FullRemap_USART3 USART3復(fù)用功能完全映射
GPIO_PartialRemap_TIM1 USART3復(fù)用功能部分映射
GPIO_FullRemap_TIM1 TIM1復(fù)用功能完全映射
GPIO_PartialRemap1_TIM2 TIM2復(fù)用功能部分映射1
GPIO_PartialRemap2_TIM2 TIM2復(fù)用功能部分映射2
GPIO_FullRemap_TIM2 TIM2復(fù)用功能完全映射
GPIO_PartialRemap_TIM3 TIM3復(fù)用功能部分映射
GPIO_FullRemap_TIM3 TIM3復(fù)用功能完全映射
GPIO_Remap_TIM4 TIM4復(fù)用功能映射
GPIO_Remap1_CAN CAN復(fù)用功能映射1
GPIO_Remap2_CAN CAN復(fù)用功能映射2
GPIO_Remap_PD01 PD01復(fù)用功能映射
GPIO_Remap_SWJ_NoJTRST 除JTRST外SWJ完全使能(JTAG+SW-DP)
GPIO_Remap_SWJ_JTAGDisable JTAG-DP失能+ SW-DP使能
GPIO_Remap_SWJ_Disable SWJ完全失能(JTAG+SW-DP)
每個(gè)功能在后面小節(jié)的應(yīng)用中體現(xiàn)。
·void GPIO_EXTILineConfig(u8 GPIO_PortSource, u8 GPIO_PinSource)
GPIO配置為外部中斷,兩個(gè)值分別為端口值和引腳。
·void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface)
最后一個(gè)配置以太網(wǎng)接口。該函數(shù)只有兩行語(yǔ)句。此處不作介紹。
例程就不做介紹了,奮斗和微雪的板子 都還不錯(cuò),初學(xué)者使用剛好。
下一節(jié)研究下定時(shí)器的使用。
1.GPIO和AFIO
GPIO寄存器
(1)兩個(gè)32位配置寄存器(GPIOx_CRL,GPIOx_CRH);
(2)兩個(gè)32位數(shù)據(jù)寄存器(GPIOx_IDR,GPIOx_ODR);
(3)一個(gè)32位置為/復(fù)位寄存器(GPIOx_BSRR);
(4)一個(gè)16位復(fù)位寄存器(GPIOx_BRR);
(5)一個(gè)32位鎖存器(GPIOx_LCKR);
當(dāng)I/O端口配置為輸入時(shí):
●
●
●
●
●
輸出配置
當(dāng)I/O端口被配置為輸出時(shí):
●
─
─
●
●
●
●
●
STM32中的配置寄存器在固件函數(shù)庫(kù)中早已生成,因此無(wú)需再對(duì)寄存器的每個(gè)設(shè)定寫定義,而是直接調(diào)用關(guān)鍵字。這樣我們可以不再關(guān)心寄存器的具體配置(因?yàn)槟且呀?jīng)在固件配置好了);因此直觀的從配置函數(shù)中去看,更能有效的提高。
GPIO相關(guān)的庫(kù)函數(shù)如下,位于在“stm32f10x_gpio.h”
GPIO相關(guān)函數(shù)如下:
void
void
void
void
uint8_t
uint16_t
uint8_t
uint16_t
void
void
void
void
void
void
void
void
void
void
以下將逐個(gè)說(shuō)明函數(shù)功能及注釋說(shuō)明:
·void
該函數(shù)原型在"stm32f10x_gpio.C"當(dāng)中,類似C++
其中是為不同組的IO口進(jìn)行寄存器值的初始化。
初始化語(yǔ)句如下:
“
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,
再追根溯源到這個(gè)函數(shù),位于“stm32f10x_rcc.C”當(dāng)中
"void
{
}
函數(shù)注釋如下:
一目了然,即配置IO口時(shí)鐘狀態(tài)為使能或者失效。
當(dāng)然在其中此函數(shù)作為一個(gè)初學(xué)實(shí)例還是值得深究的:
此處兩句即類似于C++中的斷言函數(shù),作為函數(shù)運(yùn)行的先決條件。這里將斷言函數(shù)直接說(shuō)明,在后續(xù)的實(shí)例中,仍舊會(huì)有使用到的地方。
#else
#endif
#endif
若滿足斷言值為"1"的條件,否則判定失敗輸出
再返回“assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));”此句中。“IS_RCC_APB2_PERIPH”如下定義:
·#define
此處使用到的是AP2
·#define
只為考慮還是的形參是否是“DISABLE”or“ENABLE”
“
”
而APB2RSTR則即將牽扯到RCC的設(shè)置問(wèn)題,我們下一節(jié)再講。
·void
同樣調(diào)用“RCC_APB2PeriphResetCmd”。也是串口初始化判斷
·void
寄存器手冊(cè)中記為:根據(jù)GPIO_InitStruct中指定參數(shù)初始化外設(shè)GPIOx寄存器
不想在此處在贅述此函數(shù),主要通過(guò)寫寄存器的值來(lái)配置GPI0x,GPIO_pin,GPIO_Mode,GPIO_speed,以及寫GPIO
·void
GPIO_Speed
GPIO_Speed_10MHz
GPIO_Speed_2MHz
GPIO_Speed_50MHz
GPIO_Mode_AIN
GPIO_Mode_IN_FLOATING
GPIO_Mode_IPD
GPIO_Mode_IPU
GPIO_Mode_Out_OD
GPIO_Mode_Out_PP
GPIO_Mode_AF_OD
GPIO_Mode_AF_PP
·
uint8_t
uint16_t
uint8_t
uint16_t
讀取指定管腳輸入/輸出,讀取管腳輸入/輸出數(shù)據(jù)值。
·
void
void
void
"bitval
void
設(shè)定/清除指定的數(shù)據(jù)位
·void
鎖存管腳寄存器,鎖存指定GPIO組指定引腳。
·void
配置GPIO為事件輸出,其后我們來(lái)解決這個(gè)疑問(wèn)。
·void
此函數(shù)決定了IO口的重新映射,實(shí)際是IO復(fù)用功能的實(shí)現(xiàn),GPIO_Remap選擇輸入引腳,NewState的配置值如下:GPIO_Remap_SPI1
GPIO_Remap_I2C1
GPIO_Remap_USART1
GPIO_PartialRemap_USART3
GPIO_FullRemap_USART3
GPIO_PartialRemap_TIM1
GPIO_FullRemap_TIM1
GPIO_PartialRemap1_TIM2
GPIO_PartialRemap2_TIM2
GPIO_FullRemap_TIM2
GPIO_PartialRemap_TIM3
GPIO_FullRemap_TIM3
GPIO_Remap_TIM4
GPIO_Remap1_CAN
GPIO_Remap2_CAN
GPIO_Remap_PD01
GPIO_Remap_SWJ_NoJTRST
GPIO_Remap_SWJ_JTAGDisable
GPIO_Remap_SWJ_Disable
每個(gè)功能在后面小節(jié)的應(yīng)用中體現(xiàn)。
·void
GPIO配置為外部中斷,兩個(gè)值分別為端口值和引腳。
·void
最后一個(gè)配置以太網(wǎng)接口。該函數(shù)只有兩行語(yǔ)句。此處不作介紹。
例程就不做介紹了,奮斗和微雪的板子
下一節(jié)研究下定時(shí)器的使用。
評(píng)論