【蓝桥杯嵌入式】状态机按键

        按键作为人机交互中重要的一环,是必需掌握的部分。比赛板子上一共有4个按键,分别连接到不同的IO口上(B1----PB0,B2----PB1,B3----PB2,B4----PA0)。如下图所示,按键在松开(空闲)状态时,IO口检测到电平为高电平,按键按下时,IO口检测到的为低电平。我们把相应IO口设置为输入模式,那么捕捉到低电平,我们就可以认为按键被按下了。由于物理按键存在一些抖动、振动等不确定因素,所以需要添加软件消抖(在检测到按下信号后,隔10~20ms后再次确认状态,排除干扰)。我们选择结合定时器轮询,同时使用状态机检测方法(将在下面的编程部分进行介绍),这样既可以实现消抖、多按键检测、单次起效,还可以拓展实现长短按、双按等等。

一、STM32Cube 按键的设置

复制上次的2_TIM工程文件夹,并命名为“3_KEY”,打开TEST.ioc。

Cube中将PB0,PB1,PB2,PA0设置为输入模式,上拉(Pull-up),并进行命名。按键外接上拉电阻,在空闲状态下,IO口被拉至高电平,所以选择上拉模式。

轮询用的定时器我们沿用上次设置的总控定时器TIM4,这样基本设置就好了,按“GENERATE CODE”更新工程。

二、按键(状态机)程序的实现

用Keil 5打开TEST.uvprojx,再打开USER中用于中断的interrupt.c。

我们计划通过按键来控制按钮,各按键效果:

B1:亮LD1、LD2

B2:亮LD3、LD4

B3:LD5、LD6状态翻转

B4:熄灭LD1~LD6

其他LED灯效果:LD7始终熄灭,LD8每0.5s翻转一次状态。

1、基本的状态机编程

首先,我们为状态机定义三个状态:空闲状态,未按下(IDLE)、按下待执行相应功能(PRESSED_READY)、按下功能已执行等待松开按键回到空闲状态(PRESSED_FINISH)。

我们定义了一个枚举类型变量 ButtonState,来记录这些状态。

typedef enum 
{
	IDLE,						//未按下,空闲状态
	PRESSED_READY,	//按下,待执行相应功能
	PRESSED_FINISH,	//按下,功能已执行,等待松开按键回到空闲状态
	//PRESSED_COUNT		//按下&#x
### 蓝桥杯嵌入式按键实现方法 在蓝桥杯嵌入式项目中,按键处理是一个重要的模块。为了提高代码的可读性和维护性,建议采用一种更灵活的设计方式来管理按键事件。 #### 中断驱动的状态机设计 通过将按键状态机独立出来并利用中断触发状态转移可以有效降低耦合度[^3]。这种方式不仅提高了程序结构清晰度,还增强了系统的响应速度和稳定性。 下面展示了一个简单的基于STM32微控制器平台上的C语言实现例子: ```c #include "stm32f1xx_hal.h" #define DEBOUNCE_TIME 50 /* 消抖时间 */ #define LONG_PRESS_TIME 1000 /* 长按时长 */ typedef enum { KEY_IDLE, KEY_PRESSED, KEY_LONGPRESSED, KEY_DOUBLECLICKED } KeyState; static uint32_t lastPressTime; static KeyState keyState = KEY_IDLE; void EXTI0_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_0) { static uint32_t pressStartTime; // 消除机械开关抖动影响 HAL_Delay(DEBOUNCE_TIME); switch(keyState){ case KEY_IDLE: if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==GPIO_PIN_RESET){ pressStartTime = HAL_GetTick(); keyState = KEY_PRESSED; } break; case KEY_PRESSED: if((HAL_GetTick() - pressStartTime >= LONG_PRESS_TIME)){ keyState = KEY_LONGPRESSED; // 执行长按操作... }else{ keyState = KEY_IDLE; // 单击动作执行... } break; default: break; } // 双击检测逻辑可以在主循环里完成 } } ``` 此段代码展示了如何设置外部中断服务函数以及回调机制用于捕捉按键按下事件,并根据不同条件区分单次点击、长时间按压两种情况下的不同行为。对于双击功能,则可以通过记录两次相邻的有效边沿之间的时间间隔,在适当位置加入额外判断语句即可实现。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值