【STM32】HAL库学习笔记:GPIO按键控制LED和蜂鸣器(超详细教程)

【stm32】hal库学习笔记-GPIO按键控制LED和蜂鸣器

注:本学习笔记基于stm32f4系列
使用的开发板为正点原子stmf407ZGT6探索者开发板

GPIO引脚使用时,可输入或输出数字信号
例如:
检测按键输入信号(Read_Pin)输出信号(Write_Pin)
输出信号点亮或熄灭LED

硬件特点

GPIO引脚内部结构图
GPIO引脚内部结构图

GPIO状态

  • 输入浮空状态:上拉下拉电阻均不使用(复位时状态)
  • 输入上拉状态:只使用上拉电阻-引脚外部无输入时读到的电平为高电平
  • 这里是引用

    按键按下时接地读到低电平

  • 输入下拉状态:只使用下拉电阻-引脚外部无输入时读到的电平为低电平
  • 这里是引用

  • 模拟状态:不使用任何内部的上拉下拉电阻-用于ADC输入/DAC输出引脚
  • 开漏输出(Output Open Drain)
  • 推挽输出:输出1时引脚为高电平,输出0时引脚为低电平
    若要增强引脚的输出驱动能力,则可使用上拉-如GPIO输出高电平点亮LED
  • 复用功能推挽
  • 复用功能开漏
  • 涉及到的函数

    重要函数

    HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
    HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
    HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
    

    按键控制LED

    LED部分原理图
    LED部分原理图
    按键部分原理图
    按键部分原理图

    实现功能:
    按下KEY0时,使LED0的输出翻转
    按下KEY1时,使LED1的输出翻转
    按下KEY2时,使LED0与LED1的状态都翻转

    MCU图形化配置

    连接按键的引脚选择GPIO_Input
    连接LED的引脚选择GPIO_Output
    并设置相应的用户标签

  • KEY0,KEY1,KEY2配置为上拉(Pull-up)
  • PF9,PF10设置为推挽输出(Output Push Pull)
  • 调试引脚设为串行调试引脚WSD
  • 在RCC里将HSE改为晶振

    在时钟树界面
  • 将HSE改为8MHz
  • 主锁相环选择HSE作为时钟源
  • 设置HCLK为168
  • 代码部分

    编写驱动程序

    keyled.c

    #include "keyled.h"
    //编写函数扫描被按下的按键
    KEYS ScanPressedKey(uint32_t timeout)
    {
    	uint32_t tickstart=HAL_GetTick();
    	const uint32_t btnDelay=20;//延时时间
    	while(1)
    	{
    #ifdef KEY0_Pin
    		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET)
    		{
    			HAL_Delay(btnDelay);//延时消除前抖动
    			if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET)
    			{
    				return KEY_0;
    			}
    		}
    #endif
    #ifdef KEY1_Pin
    		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
    		{
    			HAL_Delay(btnDelay);
    			if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
    			{
    				return KEY_1;
    			}
    		}
    #endif
    #ifdef KEY2_Pin
    		if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
    		{
    			HAL_Delay(btnDelay);
    			if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
    			{
    				return KEY_2;
    			}
    		}
    #endif
    #ifdef KEY_UP_Pin
    		if(HAL_GPIO_ReadPin(KEY_UP_GPIO_Port,KEY_UP_Pin)==GPIO_PIN_SET)
    		{
    			HAL_Delay(btnDelay);
    			if(HAL_GPIO_ReadPin(KEY_UP_GPIO_Port,KEY_UP_Pin)==GPIO_PIN_SET)
    			{
    				return KEY_UP;
    			}
    		}
    #endif
    		if(timeout!=KEY_WAIT_ALWAYS)
    		{
    			if((HAL_GetTick()-tickstart)>timeout)
    			{
    				break;
    			}
    	    }
    	}
    	return KEY_NONE;
    }//若没有按键被按下,超时后跳出循环
    
    

    keyled.h

    #include <main.h>
    //创建枚举类型
    typedef enum
    {
    	KEY_0=0,
    	KEY_1,
    	KEY_2,
    	KEY_UP,
    	KEY_NONE,
    }KEYS;
    //定义参数-表示一直等待按键按下
    #define KEY_WAIT_ALWAYS		0//函数声明
    KEYS ScanPressedKey(uint32_t timeout);
    #ifdef LED0_Pin
    	#define LED0_Toggle()	HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin)//实现翻转
    	#define LED0_ON()	 HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PinState PinStateGPIO_PIN_SET)//实现打开
    	#define LED0_OFF()	 HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET)//实现关闭
    #endif
    
    #ifdef LED1_Pin
    	#define LED1_Toggle()	HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin)
    	#define LED1_ON()	 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PinState PinStateGPIO_PIN_SET)
    	#define LED1_OFF()	 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET)
    #endif
    
    #ifdef Buzzer_Pin
    	#define Buzzer_Toggle()	HAL_GPIO_TogglePin(Buzzer_GPIO_Port, Buzzer_Pin)
    	#define Buzzer_ON()	 HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PinState PinStateGPIO_PIN_SET)
    	#define Buzzer_OFF()	 HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET)
    #endif
    
    
    应用驱动程序



    如此设置后出现no such file or directory,经过上网查找后找到如下解决办法

    (来自CSDN博主tuxinbang1989)

    编写主程序
    /* USER CODE BEGIN Includes */
    #include "keyled.h"
    /* USER CODE END Includes */
    
      while (1)
      {
    	  KEYS curKey=ScanPressedKey(KEY_WAIT_ALWAYS);
    	  switch (curKey)
    	  {
    	  case KEY_0:
    	  	  LED0_Toggle();
    	  	  break;
    	  case KEY_1:
    	  	  LED1_Toggle();
    	  	  break;
    	  case KEY_2:
    	  	  LED0_Toggle();
    	  	  LED1_Toggle();
    	  	  break;
    	  case KEY_UP:
    	  	  Buzzer_Toggle();
    	  	  break;
    	  default:
    		  break;
    	  }
    	  HAL_Delay(200);//消除按键弹起时的的抖动影响
    

    按键控制蜂鸣器

    有源蜂鸣器原理图
    有源蜂鸣器原理图
    有源蜂鸣器是指自带了震荡电路的蜂鸣器,这种蜂鸣器一接上电就会自己震荡发声。而如
    果是无源蜂鸣器,则需要外加一定频率(2~5Khz)的驱动信号,才会发声。
    图中 Q4 是用来扩流,R65 则是一个下拉电阻,避免 MCU 复位的时候,蜂鸣器可能发声的
    现象。BEEP 信号直接连接在 MCU 的 PF8 上面,PF8 可以做 PWM 输出,可使用 PWM 来控制蜂鸣器实现“唱歌”。

    实现功能:
    按下KEY_UP按键时,蜂鸣器输出翻转

    MCU图形化配置

    连接蜂鸣器的引脚选择GPIO_Output
    并设置相应的用户标签

  • KEY_UP配置为下拉(Pull-down)
  • PF8设置为下拉推挽输出(Output Push Pull)
  • 将初始状态改为High(防止一复位蜂鸣器就响)
  • 最大输出频率-若为无源蜂鸣器则改为High,有源滤波器都可
  • 成果演示


    上键翻转蜂鸣器状态
    KEY0翻转红灯,KEY1翻转绿灯
    KEY2同时翻转两个灯状态

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【STM32】HAL库学习笔记:GPIO按键控制LED和蜂鸣器(超详细教程)

    发表评论