4.STM32F407之HAL库——按键

使用STM32CubeMX配置工程+MDKARM编写代码实现按键控制

一、按键简介

  轻触式按键开关:按键开关是一种电子开关,属于电子元器件,使用时以满足操作力的条件向开关操作方向施压开关功能闭合接通,当撤销压力时开关即断开,其内部结构是靠金属弹片受力变化来实现通断的。
按键

按键
  连接电路或者导线的时候要注意,斜对角相连可以保证功能正常使用。如果连在①和②两侧则按键常开,失效。
  配合按键帽使用手感更佳。

二、STM32CubeMX配置

  按键和LED不太一样。LED是IO引脚的输出。按键则是IO引脚状态的读取(输入),单片机通过对IO引脚电平状态的识别,来判断按键是否按下。一般也分为共阳或者共阴。也分为独立按键和矩阵按键等等。就不细细展开了。这里用的是独立按键。

按键原理图
  从原子官方提供的原理图可以看出来,KEY0、KEY1 和 KEY2 是低电平有效的,而 KEY_UP 是高电平有效。并且KEY0接PE4、KEY1接PE3、KEY2接PE2、KEY_UP接PA0。
打开STM32CubeMX进行配置引脚。
  设置引脚输入模式为输入模式,WK_AP连接PA0,由于是高电平有效,所以设置默认为下拉。并自定义引脚标签

PA0
  KEY0-2这三个引脚的设置是一样的,低电平有效,默认设置为上拉,再自定义标签就可以了。

key0-key2

三、代码实现

  打开由STM32CubeMX生成的工程
  新建key.c和key.h文件。将文件添加到工程
  先来看看.h文件

#ifndef __KEY_H
#define __KEY_H 	

#include "main.h" 


//下面的方式是通过直接操作HAL库函数方式读取IO
#define ReadKeyRight    HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)  //KEY0按键PE4
#define ReadKeyDown     HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)  //KEY1按键PE3
#define ReadKeyLeft     HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2) 	//KEY2按键PE2
#define ReadWK_UP       HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)  //WKUP按键PA0

#define KeyRight_PRES 	1
#define KeyDown_PRES	2
#define KeyLeft_PRES	3
#define WKUP_PRES       4

uint8_t KEY_Scan(uint8_t mode);
void KeyEvent(void);

#endif

  采用宏函数编写,IO转态读取。将函数的返回值与键联系起来,每个按键对应一个返回值,编写按键扫描函数KEY_Scan()。再将按键的功能封装起来,编写成一个按键函数KeyEvent()。
  按键扫描函数沿用正点原子的官方函数,这个轮子写的很好了,没必要画蛇添足。

#include "key.h"  

//按键处理函数 正点原子的例程
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,WKUP按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
uint8_t KEY_Scan(uint8_t mode)
{
    static u8 key_up=1;     //按键松开标志
    if(mode==1)key_up=1;    //支持连按
    if(key_up&&(ReadKeyRight==0||ReadKeyDown ==0||ReadKeyLeft==0||ReadWK_UP==1))
    {
				HAL_Delay(10);
        key_up=0;
        if(ReadKeyRight==0)       return KeyRight_PRES;
        else if(ReadKeyDown ==0)  return KeyDown_PRES;
        else if(ReadKeyLeft==0)   return KeyLeft_PRES;
        else if(ReadWK_UP==1) return WKUP_PRES;          
    }else if(ReadKeyRight==1&&ReadKeyDown ==1&&ReadKeyLeft==1&&ReadWK_UP==0)key_up=1;
    return 0;   //无按键按下
}

//把按键功能集中到这里
//按下左边的按键打开LED0,按下下面的按键关闭LED0
//按下右边的按键打开LED1,按键上面的按键关闭LED1
void KeyEvent(void)
{
		u8 keyValue=KEY_Scan(0);
		switch(keyValue)
		{
			
			case KeyLeft_PRES:	Led0_On;break;
			case KeyDown_PRES:  Led0_Off;break;
			case KeyRight_PRES: Led1_On;break;
			case WKUP_PRES:     Led1_Off;break;
		}
}


  修改main.h文件,添加引用

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
typedef unsigned char u8; //key.c里面的函数用到了类型u8,所以这里要typedef一下
typedef unsigned int u16;
#include "bit_oper.h" 
#include "key.h" //添加有关按键的引用
/* USER CODE END Includes */

  编写main.c文件,修改主函数,添加按键功能,注意要把按键检测的函数放到while(1)循环的内部

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 */
	Led0_Light_N(5,500);//LED0以500毫秒间隔闪烁5次
	Led1_Light_N(5,500);//LED1以500毫秒间隔闪烁5次
	Beep_On;//蜂鸣器响十秒后关闭
	for(int i=0;i<10;i++)
	{
		HAL_Delay(1000);
	}
	Beep_Off;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		KeyEvent();//按键功能,具体看函数内部。
  }
  /* USER CODE END 3 */
}

  这样编译再下载运行就可以了,具体实现的功能是LED0以500毫秒间隔闪烁5次、LED1以500毫秒间隔闪烁5次、蜂鸣器响十秒后关闭。
  按键功能是:
    按下左边的按键打开LED0,
    按下下面的按键关闭LED0。
    按下右边的按键打开LED1,
    按键上面的按键关闭LED1。

  感谢各位的浏览。鄙人水平有限,很多地方写的感觉差强人意,如果有不对的地方欢迎指正。

### STM32F407 HAL中断配置及使用教程 #### 配置环境准备 为了成功配置和使用STM32F407上的HAL中断功能,需确保已准备好必要的开发工具。这包括但不限于STM32CubeMX用于生成初始化代码;Keil uVision或STM32CubeIDE作为集成开发环境(IDE),以及一块实际可用的STM32F407开发板[^2]。 #### 中断配置流程概述 在STM32微控制器系列中,通过HAL可以简化外设驱动程序的设计过程。对于中断机制而言,主要涉及以下几个方面的工作: - **使能时钟**:确保目标外设有足够的电源供应并处于工作状态。 - **设置优先级分组**:定义不同级别下的子优先级分配方案。 - **注册回调函数**:当特定事件触发时执行自定义逻辑。 - **启动中断服务例程(ISR)**:一旦硬件检测到相应条件满足,则自动跳转至预先设定好的ISR位置继续运行。 #### 实际操作指南 下面给出一段简单的C语言代码片段展示如何利用HAL完成GPIO端口A上按键按下产生的外部中断请求配置: ```c // 初始化NVIC (嵌套向量中断控制器), 设置EXTI Line 0 的抢占优先级为1, 子优先级也为1. __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 GPIOA 时钟 HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 1); HAL_NVIC_EnableIRQ(EXTI0_IRQn); void EXTI0_IRQHandler(void){ /* USER CODE BEGIN EXTI0_IRQn 0 */ /* USER CODE END EXTI0_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); // 调用 HAL 提供的通用处理方法 /* USER CODE BEGIN EXTI0_IRQn 1 */ /* USER CODE END EXTI0_IRQn 1 */ } // 注册回调函数,在这里可以放置用户想要响应中断的具体动作 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ if(GPIO_Pin == GPIO_PIN_0){ // 当PA0发生上升沿/下降沿变化时调用此部分代码 printf("Button pressed\n"); } } ``` 上述代码展示了针对具体应用场景——即监测某个IO引脚电平改变情况而设计的一整套解决方案。值得注意的是,这段代码仅适用于说明目的,并未涵盖所有可能遇到的实际问题及其解决办法[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值