STM32F1与STM32CubeIDE快速入门-按键与LED控制 GPIO数字输入与数字输出 GPIO(General Purpose Input Output)即通用输入输出。输入和输出是GPIO的基本特征。在前面的实例中,对GPIO做了整体概述,请参考STM32F1与STM32CubeIDE快速入门-GPIO概述与点亮LED 。在本次实例中,将着重介绍如何通过HAL库对GPIO进行基本操作。
1、HAL库中GPIO的驱动介绍 1)GPIO初始化定义:GPIO_InitTypeDef
GPIO_InitTypeDef在stm32f1xx_hal_gpio.h中定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 \*/ } GPIO_InitTypeDef;
2)GPIO外设特性
GPIO 端口,可以在多种模式下由软件单独配置:
输入模式
模拟模式
输出模式
交替功能模式
外部中断/事件线
在复位期间和刚复位后, 替代功能和外部中断线不活动,I/O 端口配置为输入浮动模式。所有 GPIO 引脚都有内部弱上拉和下拉电阻,可以激活或不激活。
在输出或交替功能模式下,每个 IO 都可以配置为开漏或推挽类型,并且可以根据 VDD 值选择 IO 速度。
所有端口都具有外部中断/事件功能。 要使用外部中断线,端口必须配置为输入模式。 所有可用的 GPIO 引脚都连接到从 EXTI0 到 EXTI15 的 16 条外部中断/事件线。
外部中断/事件控制器由连接线设备中的多达 20 个边缘检测器或其他设备中的 19 个边缘检测器组成,用于生成事件/中断请求。 每条输入线都可以独立配置选择类型(事件或中断)和相应的触发事件(上升或下降或两者兼有)。每条线也可以独立屏蔽。 挂起寄存器维护中断请求的状态线。
2、HAL的GPIO驱动使用步骤
1)启用 GPIO APB2 时钟:__HAL_RCC_GPIOx_CLK_ENABLE()
2)使用 HAL_GPIO_Init() 配置 GPIO 引脚:
使用GPIO_InitTypeDef 结构中的Mode字段配置 IO 模式
使用 GPIO_InitTypeDef 结构中的Pull字段激活上拉、下拉电阻
在输出或交替功能模式选择的情况下:通过GPIO_InitTypeDef结构中的Speed成员配置速度
当引脚用作 ADC 通道或 DAC 输出时,需要配置模拟模式
在外部中断/事件选择的情况下,GPIO_InitTypeDef 结构中的Mode成员选择类型(中断或事件)和相应的触发事件(上升或下降或两者)
3)在外部中断/事件模式选择的情况下,使用HAL_NVIC_SetPriority()配置映射到 EXTI 线的 NVIC IRQ 优先级并使用HAL_NVIC_EnableIRQ()启用它
4)使用HAL_GPIO_ReadPin()获取在输入模式下配置的引脚电平
5)使用HAL_GPIO_WritePin()或HAL_GPIO_TogglePin()设置/重置在输出模式下配置的引脚电平
6)使用HAL_GPIO_LockPin()锁定引脚配置直到下一次复位
7)在复位期间和刚复位后,交替功能未激活且GPIO引脚配置为输入浮动模式(JTAG 引脚除外)
8)当 LSE 振荡器关闭时,LSE振荡器引脚OSC32_IN和OSC32_OUT可用作通用(分别为 PC14 和 PC15)。LSE优先于GPIO功能。
9)当 HSE 振荡器关闭时,HSE 振荡器引脚OSC_IN/OSC_OUT可分别用作通用PD0和PD1。 HSE优先于GPIO 功能。
HAL库中常用的GPIO函数如下:
**HAL_GPIO_Init **:GPIO初始化
**HAL_GPIO_DeInit **:GPIO逆初始化,将GPIO的寄存设置为默认值
**HAL_GPIO_ReadPin **:读取指定引脚电平
HAL_GPIO_WritePin :设置指定引脚电平
**HAL_GPIO_TogglePin **:切换指定的 GPIO 引脚,即高低电平之间切换
**HAL_GPIO_LockPin ** **:锁定 GPIO 引脚配置寄存器
**HAL_GPIO_EXTI_IRQHandler **:处理 EXTI 中断请求
**HAL_GPIO_EXTI_Callback **:EXTI 线路检测回调
3、STM32Cube IDE工程配置 1)第一步:创建工程,请参考:STM32F1与STM32CubeIDE快速入门-GPIO概述与点亮LED
2)第二步:配置系统时钟,请参考:STM32F1与STM32CubeIDE快速入门-GPIO概述与点亮LED
3)第三步:配置引脚:
将PE2、PE3、PE4、PE5作为按键输入引脚
将PC6、PC7、PD6、PD13作为LED输出引脚
按键电路原理图如下:
LED电路原理图如下:
4)第四步,保存配置,生成代码
4、代码实现 STM32Cube IDE根据配置生成了相应的文件。在本次实例中,只需要在main.c中添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 /\* USER CODE BEGIN Header \*/ /\*\* \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* \* @file : main.c \* @brief : Main program body \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* \* @attention \* \* <h2><center>© Copyright (c) 2021 STMicroelectronics. \* All rights reserved.</center></h2> \* \* This software component is licensed by ST under BSD 3-Clause license, \* the "License"; You may not use this file except in compliance with the \* License. You may obtain a copy of the License at: \* opensource.org/licenses/BSD-3-Clause \* \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* \*/ /\* USER CODE END Header \*/ /\* Includes ------------------------------------------------------------------\*/ #include "main.h" /\* Private includes ----------------------------------------------------------\*/ /\* USER CODE BEGIN Includes \*/ /\* USER CODE END Includes \*/ /\* Private typedef -----------------------------------------------------------\*/ /\* USER CODE BEGIN PTD \*/ /\* USER CODE END PTD \*/ /\* Private define ------------------------------------------------------------\*/ /\* USER CODE BEGIN PD \*/ /\* USER CODE END PD \*/ /\* Private macro -------------------------------------------------------------\*/ /\* USER CODE BEGIN PM \*/ /\* USER CODE END PM \*/ /\* Private variables ---------------------------------------------------------\*/ /\* USER CODE BEGIN PV \*/ /\* USER CODE END PV \*/ /\* 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 \*/ if (HAL\_GPIO\_ReadPin(GPIOE, GPIO_PIN_5) == GPIO_PIN_RESET) { // 读取引脚电平 HAL\_GPIO\_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET); // 设置引脚为高电平 HAL\_Delay(100); // 延时100ms HAL\_GPIO\_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET); // 将引脚设置为低电平 } if (HAL\_GPIO\_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET) { // HAL\_GPIO\_TogglePin(GPIOC, GPIO\_PIN\_7); HAL\_GPIO\_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); HAL\_Delay(100); HAL\_GPIO\_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); } if (HAL\_GPIO\_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET) { // HAL\_GPIO\_TogglePin(GPIOD, GPIO\_PIN\_6); HAL\_GPIO\_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_SET); HAL\_Delay(100); HAL\_GPIO\_WritePin(GPIOD, GPIO_PIN_6, GPIO_PIN_RESET); } if (HAL\_GPIO\_ReadPin(GPIOE, GPIO_PIN_2) == GPIO_PIN_RESET) { // HAL\_GPIO\_TogglePin(GPIOD, GPIO\_PIN\_13); HAL\_GPIO\_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); HAL\_Delay(100); HAL\_GPIO\_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET); } HAL\_Delay(10); } /\* USER CODE END 3 \*/ } /\*\* \* @brief System Clock Configuration \* @retval None \*/ void SystemClock\_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; /\*\* Initializes the RCC Oscillators according to the specified parameters \* in the RCC\_OscInitTypeDef structure. \*/ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL\_RCC\_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error\_Handler(); } /\*\* Initializes the CPU, AHB and APB buses clocks \*/ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL\_RCC\_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error\_Handler(); } } /\*\* \* @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\_GPIOE\_CLK\_ENABLE(); \_\_HAL\_RCC\_GPIOD\_CLK\_ENABLE(); \_\_HAL\_RCC\_GPIOC\_CLK\_ENABLE(); /\*Configure GPIO pin Output Level \*/ HAL\_GPIO\_WritePin(GPIOD, GPIO_PIN_13 | GPIO_PIN_6, GPIO_PIN_RESET); /\*Configure GPIO pin Output Level \*/ HAL\_GPIO\_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); /\*Configure GPIO pins : PE2 PE3 PE4 PE5 \*/ GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL\_GPIO\_Init(GPIOE, &GPIO_InitStruct); /\*Configure GPIO pins : PD13 PD6 \*/ GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL\_GPIO\_Init(GPIOD, &GPIO_InitStruct); /\*Configure GPIO pin : PC6 \*/ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL\_GPIO\_Init(GPIOC, &GPIO_InitStruct); /\*Configure GPIO pin : PC7 \*/ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL\_GPIO\_Init(GPIOC, &GPIO_InitStruct); } /\* USER CODE BEGIN 4 \*/ /\* USER CODE END 4 \*/ /\*\* \* @brief This function is executed in case of error occurrence. \* @retval None \*/ void Error\_Handler(void) { /\* USER CODE BEGIN Error\_Handler\_Debug \*/ /\* User can add his own implementation to report the HAL error return state \*/ \_\_disable\_irq(); while (1) { } /\* USER CODE END Error\_Handler\_Debug \*/ } #ifdef USE\_FULL\_ASSERT /\*\* \* @brief Reports the name of the source file and the source line number \* where the assert\_param error has occurred. \* @param file: pointer to the source file name \* @param line: assert\_param error line source number \* @retval None \*/ void assert\_failed(uint8_t \*file, uint32_t line) { /\* USER CODE BEGIN 6 \*/ /\* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) \*/ /\* USER CODE END 6 \*/ } #endif /\* USE\_FULL\_ASSERT \*/ /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* (C) COPYRIGHT STMicroelectronics \*\*\*\*\*END OF FILE\*\*\*\*/
文章来源: https://iotsmart.blog.csdn.net/article/details/123176631
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!