【STM32】HAL库-利用状态机检测按键

5 篇文章 2 订阅
5 篇文章 1 订阅
文章介绍了如何使用STM32进行按键控制LED灯,通过状态机和定时中断结合的方式实现按键去抖动,以提高处理器效率。状态机包括现态、条件、动作和次态四个要素,并详细描述了按键的三个状态:抬起、消抖和等待释放。实验设计中,使用CubeMX配置STM32引脚和定时器,通过定时中断调用按键扫描函数KeyScan(),在后台程序中响应按键事件,实现LED灯状态翻转。
摘要由CSDN通过智能技术生成

【学习记录】STM32学习记录(三)按键控制LED灯,在这篇应用中,按键的去抖动采用了软件延时的方法,利用接口函数HAL_Delay()进行延时。这种延时去抖动的方法会占用处理器的执行时间,在延时过程中,处理器无法处理其他事务,从而降低了处理器的利用率。

在工程实际开发应用中,一般采用状态机和定时中断相结合的方式来完成按键的检测。

状态机是一个抽象的概念,表示把一个过程抽象为若干个状态之间的转换,这些状态之间存在一定的联系。状态机主要包括四个要素:

1、现态:是指当前所处的状态。

2、条件:当一个条件满足后,将会触发一个动作,或者执行一次状态的迁移。

3、动作:条件满足后执行的具体操作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

4、次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”且被激活,就转变为新的“现态”了。

四要素理解:状态机在当前状态(现态)下重复执行某一动作,并且不断检测跳转状态的条件。当突然满足某一条件后,开始进入下一个状态(次态),并且重复另外的动作。此时的次态变为现态。

状态机编程步骤:1、分析产品的功能需求,提取状态;2、画出状态图,理清状态的切换关系,标注状态转换的条件;3、明确状态机里要实现的功能;4、编写代码。

一般的状态机通过switch分支语句实现。

对于按键监测,我们将单个按键作为一个简单的系统,根据按键的整个工作过程对按键的动作和按键的确认过程进行分析,并用状态转换图表示,然后根据状态图编写应用程序。

根据状态机的原理,我们可以将按键过程抽象为三个状态:

按键抬起状态:按键没有按下。

按键消抖状态:消除按键抖动。

按键等待释放状态:等待按键释放。

具体的状态转换过程如下:

处于按键抬起状态时,如果按键信号有效(按键控制引脚读取到有效电平),则转换到按键消抖状态,开始准备消除按键的抖动。如果按键信号无效,则保持当前状态不变。

处于按键消抖状态时,如果按键信号有效,则表明按键抖动已经消除,按键处于稳定闭合状态,可以获取当前按键所对应白编号(按键译码),并转换到按键等待释放状态如果按键信号无效,则表示之前的按键信号可能是干扰信号,应该返回按键抬起状态。

处于按键等待释放状态时,如果按键信号有效,则表示还处在按键按下状态,不进行状态改变。如果按键信号无效,则表明按键已经释放,应该转换到按键抬起状态。至此已经完成了一次按键检测的全过程。

按键的状态转换过程及转换条件如下图所示。

实验内容:利用状态机设计思想编写按键处理程序,按键按下后执行操作:翻转LED1的状态。

实验设计思路:

  • 设计一个按键状态数据类型 KEY_STATE,利用枚举类型实现,包含三个枚举成员KEY_UP表示按键抬起状态,KEY_DEBOUNCE 表示按键消抖状态KEY_WAIT_RELEASE表示按键等待释放状态。
  • 设计一个按键扫描函数 KeyScan(),利用Switch-Case 多分支语,通过检测按键脚的电平来实现按键状态的转换。
  • 利用定时器产生 10 ms 的定时中断,在定时中断服务程序中调用按键扫描函数。按键扫描函数每隔 10 ms 调用一次,这个时间间隔可以用来消除按键的抖动,提高 CPU 的利用率。
  • 采用前后台编程模式。设置一个标志变量 KeyFlag,由定时中断对 KeyFlag 置位。后台程序在 while(1)循环中不断检测 KeyFlag,为真则执行按键的处理任务。

实验外设配置

使用正点原子探索者。

 

 

  1. 打开CubeMX进行配置选择stm32F407ZGT6进行相应引脚配置。PE4引脚设置为GPIO_Input,PF10引脚设置为GPIO_Output。
  2. 进行时钟树配置

      

     3.进行定时器的配置,激活tim1(可以选用其它的)

     4.生成代码

实验代码

1.数据类型设计、变量定义及函数声明

/* USER CODE BEGIN PTD */
typedef enum{
	KEY_UP,						//按键抬起
	KEY_DEBOUNCE,			//按键消抖
	KEY_WAIT_RELEASE	//按键等待释放
}KEY_STATE;
/* USER CODE END PTD */

/* USER CODE BEGIN PV */
KEY_STATE KeyState=KEY_UP;//按键状态,设置按键抬起为初试状态
uint8_t KeyFlag=0;				//按键有效检测标识符,0无效,1有效
/* USER CODE END PV */

/* USER CODE BEGIN PFP */
void KeyScan();//按键扫描函数声明
/* USER CODE END PFP */

2.按键处理程序 

/* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);//启动定时器1,使能定时器1中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(KeyFlag)
		{
			KeyFlag=0;
			HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

 3.按键扫描程序

/* USER CODE BEGIN 4 */
void KeyScan()
{
	switch(KeyState)
	{
		case KEY_UP:
		{
			//读到低电平,转换到按键消除状态
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==GPIO_PIN_RESET)
			{
				KeyState=KEY_DEBOUNCE;
			}
			break;
		}
		case KEY_DEBOUNCE:
		{
			//读到低电平,转换到按键等待释放状态,并设置按键有效标识
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==GPIO_PIN_RESET)
			{
				KeyState=KEY_WAIT_RELEASE;
				KeyFlag=1;
			}
			//读到高电平,说明是干扰信号,转换到按键抬起状态
			else
			{
				KeyState=KEY_UP;
			}
			break;
		}
		case KEY_WAIT_RELEASE:
		{
			//读到高电平,说明按键释放,转换到按键抬起状态
			if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==GPIO_PIN_SET)
			{
				KeyState=KEY_UP;
			}
			break;
		}
		default:break;
	}
}
/* USER CODE END 4 */

 4.定时器中断回调函数

/* USER CODE BEGIN 0 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

  if(htim->Instance==htim1.Instance)

       {

              KeyScan();

       }

}

/* USER CODE END 0 */

### 回答1: STM32 HAL库提供了许多按键处理函数,用于轻松实现按键功能,其中包括消抖处理。下面是一个简单的按键消抖处理的示例代码: ``` #include "stm32xxxx_hal.h" GPIO_TypeDef* GPIO_PORT[] = {BUTTON1_GPIO_Port, BUTTON2_GPIO_Port, BUTTON3_GPIO_Port}; const uint16_t GPIO_PIN[] = {BUTTON1_Pin, BUTTON2_Pin, BUTTON3_Pin}; uint32_t debounce_time = 50; // 定义消抖时间,单位ms uint32_t button_state = 0; // 按键状态,0表示未按下,1表示按下 uint32_t button_last_state = 0; // 上一次按键状态 uint32_t button_changed_time = 0; // 按键状态改变的时间 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { // 获取按键状态 button_state = HAL_GPIO_ReadPin(GPIO_PORT[0], GPIO_PIN[0]); // 判断按键状态是否改变 if(button_state != button_last_state) { // 获取当前时间 uint32_t current_time = HAL_GetTick(); // 判断是否达到消抖时间 if((current_time - button_changed_time) > debounce_time) { button_last_state = button_state; // 更新按键状态 button_changed_time = current_time; // 更新按键状态改变的时间 } } } int main(void) { HAL_Init(); // 配置按键引脚为输入模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN[0]; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIO_PORT[0], &GPIO_InitStruct); while(1) { if(button_last_state == 1) { // 按键已经按下 } else { // 按键未按下 } } } ``` 在上述代码中,按键的引脚被配置为下降沿触发中断模式。当按键被按下时,将会调用HAL_GPIO_EXTI_Callback函数,该函数将获取按键状态并进行消抖处理。如果按键状态发生改变并且达到了消抖时间,函数将更新按键状态和状态改变时间。最后,在主循环中,可以使用button_last_state变量获取当前按键状态。 ### 回答2: 按键消抖是为了解决按键在接触和释放过程中可能出现的抖动现象,确保按键输入稳定可靠。基于STM32HAL库按键消抖代码可以按照以下步骤实现: 1. 配置按键引脚:在GPIO初始化的时候,设置按键引脚为输入模式,同时开启外部中断功能。 2. 初始化外部中断:使用HAL库提供的函数,初始化外部中断。例如,使用HAL_GPIO_Init()函数初始化GPIO引脚。 3. 编写中断处理函数:使用HAL库的外部中断处理函数,编写中断处理函数。当检测按键状态发生变化时,该中断函数会被触发。 4. 添加按键消抖功能:在中断处理函数中加入按键消抖的代码。可以通过使用延时函数或软件定时器的方式来实现按键的延时处理。 5. 读取按键状态:在主程序中通过使用HAL库提供的函数,读取按键的状态。例如,使用HAL_GPIO_ReadPin()函数读取按键引脚的状态。 6. 判断按键的有效按下:根据实际需求,判断按键是否为有效按下状态。可以使用计数器或状态机的方法进行判断。 7. 执行相应的操作:如果判断按键为有效按下状态,根据实际需求,执行相应的操作。 通过以上步骤,可以实现基于STM32HAL库按键消抖代码。按键消抖可以确保按键输入的准确性和稳定性,提升系统可靠性和用户体验。 ### 回答3: 按键消抖是在按下或释放按键时,为了避免产生误触发信号而采取的一种技术。基于stm32hal库按键消抖代码可以通过以下步骤实现。 首先,需要使用HAL库中的GPIO模块进行按键的初始化。通过设置GPIO引脚的模式为输入模式,同时配置GPIO的上拉或下拉电阻,以确保按键的输入可靠。 然后,我们可以利用HAL库中的外部中断模块来检测按键的状态变化。外部中断可以检测按键的按下和释放动作,并且会产生中断信号,从而通知主程序进行相应的处理。 在中断服务函数中,需要进行按键的消抖处理。最常用的消抖方法是软件消抖,即通过延时一段时间来稳定按键的状态。可以使用HAL库中的延时函数进行延时操作。 在延时结束后,再次读取按键的状态。如果按键的状态与延时前相同,则可以认为按键的状态没有发生变化,即按键的状态稳定。否则,需要重新进行延时。 最后,根据按键的稳定状态进行相应的处理。可以通过判断按键的按下、释放状态来实现不同功能的触发。 这是一个简单的基于stm32hal库按键消抖代码实现。具体的代码实现可以根据具体的需求进行调整和修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值