项目&教程仓库 :-STM32-RoboMaster-
0.0 一点点声明
本文以及以后的所有属于RoboMaster主题STM32系列的文章,均以RoboMaster开发板A型 为说明和测试目标,其芯片代号为STM32F427IIHx ,如果您的芯片代号不同,则不能直接使用本教程代码和引脚配置,请酌情修改!
1.0 什么是GPIO?
General Purpose Input Output 通用输入/输出端口
GPIO接脚可以供使用者由程控自由使用,PIN脚依现实考量可作为通用输入 ( GPI ) 或通用输出 ( GPO ) 或通用输入与输出 ( GPIO ) 。在嵌入式系统中,经常需要控制许多结构简单的外部设备或者电路,这些设备有的需要通过CPU控制,有的需要CPU提供输入信号。对设备的控制,使用传统的串口或者并口就显得比较复杂,所以,在嵌入式微控制器上通常提供了一种“通用可编程I/O端口”,也就是GPIO。一个GPIO端口至少需要两个寄存器,一个做控制用的“通用IO端口控制寄存器”,还有一个是存放数据的“通用I/O端口数据寄存器”。数据寄存器的每一位是和GPIO的硬件引脚对应的,而数据的传递方向是通过控制寄存器设置的,通过控制寄存器可以设置每一位引脚的数据流向。
2.0 GPIO在哪里?
在开发板A型中,提供了18个用户自定义GPIO
上图中,26即为GPIO,位于开发板A型的中间位置
这是GPIO的具体引脚图,在配置芯片引脚时请务必核实引脚号是否正确
RoboMaster同样也非常体贴地预先将一些GPIO接到了用户自定义LED上,在2.1图中的位置为10和18,10的LED×8皆为绿色,而18的LED×2则是一绿一红,在用户自定义按键附近。只能设置为GPIO_Output模式。
用户自定义按键(白色按键,黑色按键是STM32重启按键)。可以设置为GPIO_Input模式,或者GPIO_EXTI2模式(用于Interrupt 中断,现在不用理解这个,下个教程会讲)
3.0 如何使用GPIO?
在下文中,几乎任何HAL函数的参数都需要外设和引脚,但是在比如Arduino的平台上,只需要引脚即可。其原因在于,对于STM32,一个外设可以连接众多引脚,在配置的时候,这些引脚都使用同一份外设配置,但是实际使用的时候,可以分别控制。
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
参数
GPIOx
:想要读取的GPIO所属的外设
GPIO_Pin
:想要读取的GPIO的引脚
返回值
GPIO_PinState
:当I/O为低 ( 0 ) 时,返回GPIO_PIN_RESET
;当I/O为高 ( 1 ) 时,返回GPIO_PIN_SET
void HAL_GPIO_WritePin (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
参数
GPIOx
:想要写入的GPIO所属的外设
GPIO_Pin
:想要写入的GPIO的引脚
PinState
:想要写入的GPIO状态【GPIO_PIN_RESET
/ GPIO_PIN_SET
】
void HAL_GPIO_TogglePin (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
参数
GPIOx
:想要反转的GPIO所属的外设
GPIO_Pin
:想要反转的GPIO的引脚
如果GPIO状态为GPIO_PIN_RESET
,则改为GPIO_PIN_SET
; 如果GPIO状态为GPIO_PIN_SET
,则改为GPIO_PIN_RESET
。
HAL_StatusTypeDef HAL_GPIO_LockPin (GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
参数
GPIOx
:想要锁死的GPIO所属的外设
GPIO_Pin
:想要锁死的GPIO的引脚
锁死的是该GPIO的配置,而不是状态。任何尝试修改其配置的操作都会失败,除非重置GPIO。
void HAL_GPIO_DeInit (GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
参数
GPIOx
:想要重置的GPIO所属的外设
GPIO_Pin
:想要重置的GPIO的引脚
重置GPIO到默认的配置(Input Floating模式)。用于当我们不再使用某个外设时,节约电量,避免额外的消耗。
4.0 练习项目 4.1 项目简介
按键版流水灯 :按下白色按键后,依次让自带的LED灯按顺序亮起,或者依次熄灭
4.2 芯片配置
4.3 项目代码
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 244 245 246 247 248 249 250 251 252 253 254 #include "main.h" void SystemClock_Config (void ) ;static void MX_GPIO_Init (void ) ;int main (void ) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1 ) { if (HAL_GPIO_ReadPin(Button_GPIO_Port,Button_Pin) == GPIO_PIN_SET){ HAL_Delay(500 ); HAL_GPIO_TogglePin(LD_RED_GPIO_Port,LD_RED_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD_GREEN_GPIO_Port,LD_GREEN_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD1_GPIO_Port,LD1_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD3_GPIO_Port,LD3_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD6_GPIO_Port,LD6_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD7_GPIO_Port,LD7_Pin); HAL_Delay(100 ); HAL_GPIO_TogglePin(LD8_GPIO_Port,LD8_Pin); } } }void SystemClock_Config (void ) { RCC_OscInitTypeDef RCC_OscInitStruct = {0 }; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0 }; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } }static void MX_GPIO_Init (void ) { GPIO_InitTypeDef GPIO_InitStruct = {0 }; __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOG, LD8_Pin|LD7_Pin|LD6_Pin|LD5_Pin |LD4_Pin|LD3_Pin|LD2_Pin|LD1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD_RED_GPIO_Port, LD_RED_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LD_GREEN_GPIO_Port, LD_GREEN_Pin, GPIO_PIN_RESET); GPIO_InitStruct.Pin = LD8_Pin|LD7_Pin|LD6_Pin|LD5_Pin |LD4_Pin|LD3_Pin|LD2_Pin|LD1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); GPIO_InitStruct.Pin = Button_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(Button_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = LD_RED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD_RED_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = LD_GREEN_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD_GREEN_GPIO_Port, &GPIO_InitStruct); }void Error_Handler (void ) { }#ifdef USE_FULL_ASSERT void assert_failed (uint8_t *file, uint32_t line) { }#endif
4.4 效果展示