背景
在上一講STM32 CubeMX 學習:搭建開發環境中,我們已經利用CubeMx搭建了可編譯的工程。
今天就開始來介紹STM32 GPIO的有關知識,以及如何驅動它。
HOST-OS : Windows-10
STM32 Cube :v5.6
MCU : STM32F429
LIB : stm32cube_fw_f4_v1250
知識
在STM32中,GPIO可以被用作:
- 中斷源(GPIO_MODE_IT)和事件源(GPIO_MODE_EVT)
- 接收模擬量(GPIO_MODE_ANALOG)
- 復用I/O,(比如可以被作為串口模塊使用,要用GPIO_MODE_AF_x來設置)
- 設置輸入或者輸出
當作為輸入或者輸出時,GPIO有這些屬性:輸入輸出方向;也可以設置速度,上下拉,推挽開漏等電器特性。
在Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h
中有關於 GPIO屬性的 定義。
/**
* @brief GPIO Init structure definition
*/
typedef struct
{
uint32_t Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
uint32_t Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIO_mode_define */
uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
This parameter can be a value of @ref GPIO_pull_define */
uint32_t Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIO_speed_define */
uint32_t Alternate; /*!< Peripheral to be connected to the selected pins.
This parameter can be a value of @ref GPIO_Alternate_function_selection */
}GPIO_InitTypeDef;
Pin : 指定的引腳號,右值表達式可以是 GPIO_PIN_0 ~ GPIO_PIN_15, GPIO_PIN_All 任意相或
Mode: 引腳的模式(作為中斷時還有更多的選項)
- GPIO_MODE_INPUT 浮空輸入模式:電平狀態取決於GPIO外部的電平狀態;若在GPIO外部的引腳懸空時,讀取結果是不確定的。
- GPIO_MODE_OUTPUT_PP 推挽(Pull)輸出模式(輸出較大電流):推拉輸出 既提高電路的負載能力,又提高開關速度。
- GPIO_MODE_OUTPUT_OD 開漏(Drain)輸出模式(一般外接上拉電阻,如果外部不接上拉電阻只能輸出低電平),可用於不同電壓的系統之間的通信
- GPIO_MODE_AF_PP 復用推挽輸出模式
- GPIO_MODE_OUTPUT_OD 復用開漏輸出模式
- GPIO_MODE_ANALOG 復用模擬輸入輸出模式(ADC/DAC專用)
Pull:上/下拉模式
- GPIO_NOPULL 無(針對輸出模式)
- GPIO_PULLUP 上拉輸入(針對輸入模式)
- GPIO_PULLDOWN 下拉輸入(針對輸入模式)
假設有一個GPIO口接到了 一個按鍵的一端,在此時:
- 如果按鍵的右端接正電源,那么就要 為 GPIO_PULLDOWN(下拉模式),因為這樣才能使得按鍵按下去的時候,能把I / O腳拉高,否則按鍵的功能等於擺設。
- 同理,如果按鍵另一端接地,我們就要設置為GPIO_PULLUP(上拉模式)了。
Speed:IO口速率(I/O口驅動電路的響應速度)
當STM32的GPIO端口設置為輸出模式時,有三種速度可以選擇:2MHz、10MHz和50MHz,通過選擇速度來選擇不同的驅動電路,達到最佳的噪聲控制和降低功耗的目的。(高頻的驅動電路,噪聲也高,當不需要高的輸出頻率時,請選用低頻驅動電路,這樣非常有利於提高系統的EMI性能。)
STM32F429的端口輸出速率為括號內容:
- GPIO_SPEED_LOW; (2) 2MHz注意:
- GPIO_SPEED_MEDIUM; (25) 12.5MHz ~ 50MHz
- GPIO_SPEED_FAST; (50) 25MHz ~ 100 MHz
- GPIO_SPEED_HIGH; (100) 50MHz ~ 200MHz
Alternate:復用功能
本節課不講。
CubeMx對GPIO的配置
注意,使用GPIO之前需要配置相應的時鍾。當配置了引腳而顯示了
⚠RCC
,證明需要RCC沒有配置好。
1)在Pinout& Confiurgation
頁的Pinout view
中,點擊引腳,設置為GPIO_Input
或GPIO_Output
。
2)點擊左欄的GPIO
,選擇配置的引腳,在界面下方中部靠左的位置可以看到 類似PF4 Configuration
這一欄,根據引腳輸入輸出類型的不同,有這些選項
- GPIO output level(初始化輸出電平)
- GPIO mode(模式)
- GPIO Pull-up/Pull-down(上下拉)
- Maximum output speed (輸出響應速度)
- User Label(用戶標簽): 可以標記這個引腳是做什么用的,提高可讀性。
3)點擊右上角的GENERATE CODE
生成工程
4)使用外部的工具鏈編譯工程,確保沒有問題。
代碼分析
我們看關鍵函數
初始化
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4|GPIO_PIN_5, GPIO_PIN_SET);
/*Configure GPIO pin : PF0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pin : PF4 */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pin : PF5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
}
讀寫有關api
讀取引腳
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
返回值: GPIO_PIN_SET(1) 或者 GPIO_PIN_RESET(0)
參數:
GPIOx : 端口,可以是 GPIOA ~ GPIOK
GPIO_Pin:引腳,可以是 GPIO_PIN_0 ~ GPIO_PIN_15
范例:
// 將 GPIOF 的 Pin5 設置為 低電平
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_5, GPIO_PIN_RESET);
設置引腳
// 設置
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
// 翻轉引腳電平
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
參數:
GPIOx : 端口,可以是 GPIOA ~ GPIOK
GPIO_Pin:引腳,可以是 GPIO_PIN_0 ~ GPIO_PIN_15, GPIO_PIN_All 任意相或
PinState:電平狀態, GPIO_PIN_SET(1) 或者 GPIO_PIN_RESET(0)