关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

STM32使用HAL库操作GPIO

发布时间:2023-06-30 00:00:35
一 初始化GPIO使用HAL库的优点在于不用手动添加初始化的代码了,CubeMX会根据软件设置自动生成。 自动生成的HAL库GPIO初始化代码: 复制代码复制代码static void MX_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStruct; / GPIO Ports Clock Enable / HAL_RCC_GPIOH_CLK_ENABLE(); HAL_RCC_GPIOD_CLK_ENABLE(); /Configure GPIO pin Output Level / HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET); /Configure GPIO pin : PD11 / GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /Configure GPIO pins : PD12 PD13 PD14 PD15 / GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); }复制代码复制代码顺序:(1)定义结构体变量。(2)使能时钟。(3)配置初始化电平。(4)通过结构体变量初始化GPIO。 1.首先定义一个结构体变量GPIO_InitStruct,该变量类型是GPIO_InitTypeDef。 GPIO_InitTypeDef 定义如下: 复制代码复制代码/** @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;复制代码复制代码 作用是:设置要用的是哪个引脚、引脚工作模式、上拉还是下拉、速度、XX这个还不知道是干嘛的XX。 2.使能时钟。 / GPIO Ports Clock Enable / HAL_RCC_GPIOH_CLK_ENABLE(); HAL_RCC_GPIOD_CLK_ENABLE();这里使能时钟的方法与标准库不一样,HAL库其实是宏定义,标准库则是函数。 宏定义(使能H口的宏定义): 复制代码复制代码 define __HAL_RCC_GPIOH_CLK_ENABLE() do { \ __IO uint32_t tmpreg = 0x00U; \ SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ /* Delay after an RCC peripheral clock enabling */ \ tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ UNUSED(tmpreg); \ } while(0U) 复制代码复制代码这里使能H口是因为H口接的外部晶振。 3.配置引脚的初始化电平。 /Configure GPIO pin Output Level / HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);这里设置D口的pin12、pin13、pin14、pin15为高电平。如果最后一个参数是GPIO_PIN_RESET则为低电平。 4.通过结构体变量配置具体的引脚。 复制代码复制代码 /Configure GPIO pin : PD11 / GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /Configure GPIO pins : PD12 PD13 PD14 PD15 / GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);复制代码复制代码 PD11为输入,上拉。PD12-15为推挽输出。所以分开配置。 总结一下:(1)定义结构体变量。(2)使能时钟。(3)配置初始化电平。(4)通过结构体变量初始化GPIO。 其中,(3)和(4)可调换顺序 二 功能解释1.系统分析。 STM32F4Discovery的PD12-15的四个引脚是LED。 我们要做的功能是按键一次点亮一个LED(顺时针PIN12-15,从PIN12开始)并关闭上一个LED。 首先我们需要一个标志变量来代表当前正在亮的LED: int LEDNUM_Flag = 12;流程:按键扫描 -> 读到Pin11按下 -> 关闭当前LEDNUM_Flag代表的LED(正在亮的) -> LEDNUM_Flag+1 -> 点亮当前LEDNUM_Flag代表的LED; 2.按键输入。 复制代码复制代码_Bool GetPress(void){ if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0) { HAL_Delay(10);//防抖 if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0) { while(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0)//等待按键抬起。 {;} return 1; } else return 0; } else return 0;}复制代码复制代码 3.点亮LED。 复制代码复制代码void TurnOnLED(int flag){ switch(flag) { case 12 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); break; case 13 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); break; case 14 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); break; case 15 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); break; }}复制代码复制代码 4.关闭LED。 复制代码复制代码void TurnOffLED(int flag){ switch(flag) { case 12 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); break; case 13 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET); break; case 14 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); break; case 15 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET); break; }}复制代码复制代码 5.标志变量自加。 复制代码复制代码void FlagPlus(int flag){ (flag)++; if((flag)==16) { (flag)=12; }}复制代码复制代码 这里一定要用指针,因为函数参数是值传递所以只能用指针来改变LEDNUM_Flag。 6.整合代码。 复制代码复制代码 include "main.h" include "stm32f4xx_hal.h" void SystemClock_Config(void);static void MX_GPIO_Init(void); int LEDNUM_Flag = 12; _Bool GetPress(void); void TurnOnLED(int flag); void TurnOffLED(int flag); void FlagPlus(int *flag); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); //最开始先点亮PD12的LED HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); while (1) { //有按键按下 if(GetPress()==1) { TurnOffLED(LEDNUM_Flag); FlagPlus(&LEDNUM_Flag); TurnOnLED(LEDNUM_Flag); } }} /* System Clock Configuration /void SystemClock_Config(void){ RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; /**Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 168; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { _Error_Handler(FILE, LINE); } /**Initializes the CPU, AHB and APB busses 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_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { _Error_Handler(FILE, LINE); } /**Configure the Systick interrupt time */ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); /**Configure the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); / SysTick_IRQn interrupt configuration / HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);} /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */static void MX_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStruct; / GPIO Ports Clock Enable / HAL_RCC_GPIOH_CLK_ENABLE(); HAL_RCC_GPIOD_CLK_ENABLE(); /Configure GPIO pin Output Level / HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET); /Configure GPIO pin : PD11 / GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /Configure GPIO pins : PD12 PD13 PD14 PD15 / GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////_Bool GetPress(void){ if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0) { HAL_Delay(10); if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0) { while(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11)==0) {;} return 1; } else return 0; } else return 0;} void TurnOnLED(int flag){ switch(flag) { case 12 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); break; case 13 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET); break; case 14 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); break; case 15 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET); break; }} void TurnOffLED(int flag){ switch(flag) { case 12 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); break; case 13 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET); break; case 14 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); break; case 15 : HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET); break; }} void FlagPlus(int flag){ (flag)++; if((flag)==16) { (flag)=12; }}///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// /** @brief This function is executed in case of error occurrence. @param None @retval None/void _Error_Handler(char file, int line){ / USER CODE BEGIN Error_Handler_Debug // User can add his own implementation to report the HAL error return state /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 复制代码复制代码三 重要的API。复制代码复制代码//IO口使能, 注意这里是D口__HAL_RCC_GPIOD_CLK_ENABLE(); //设置推挽输出的IO口输出电平为低HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); //设置推挽输出的IO口输出电平为高HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); //初始化一个IO口为输入GPIO_InitStruct.Pin = GPIO_PIN_11;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); //初始化IO为推挽输出GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); //读取一个输入IO口的电平HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_11);复制代码

/template/Home/leiyu/PC/Static