欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > STM32——KEY按键

STM32——KEY按键

2025/1/31 14:09:22 来源:https://blog.csdn.net/pyh1322712308/article/details/145185128  浏览:    关键词:STM32——KEY按键

一、基础工程

1. 查看引脚

B1~B4 对应引脚 为 PB0,PB1,PB2,PA0。按键按下后,接入低电平;抬起后为高电平。

2. CubeMX配置

4个对应引脚配置成 GPIO_Input。

3. 所用HAL库函数

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{GPIO_PinState bitstatus;/* Check the parameters */assert_param(IS_GPIO_PIN(GPIO_Pin));if ((GPIOx->IDR & GPIO_Pin) != 0x00U){bitstatus = GPIO_PIN_SET;}else{bitstatus = GPIO_PIN_RESET;}return bitstatus;
}

功能:读取引脚电平状态

参数说明:    

GPIOx:端口号 GPIOA,GPIOB,GPIOC    

GPIO_Pin:引脚号 GPIO_PIN_0,GPIO_PIN_1,GPIO_PIN_2 ...

返回值:    

GPIO_PinState PinState:引脚的状态 GPIO_PIN_SET , GPIO_PIN_RESET

4. 编写Key_Scan()函数

uint8_t Key_Scan(void)
{uint8_t key_val=0;
//PB0if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET){key_val=1;}
//PB1if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET){key_val=2;}
//PB2if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET){key_val=3;}
//PA0if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET){key_val=4;}return key_val;
}

5. 简单的例子

  while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */key_val=Key_Scan();if(key_val==1){ucled ^= 0x01;}Led_Disp(ucled);}

二、按键代码模板

void Key_Proc(void)
{key_val = Key_Scan();key_down = key_val & (key_val ^ key_old);key_up = ~key_val & (key_val ^ key_old);key_old = key_val;if(key_down==1)//1~4{//按键1按下,执行相应操作}
}
  • key_val 读取按键值
  • key_down 按键下降沿检测,只在按键按下瞬间为按键值,其他时刻全为0
  • key_up 按键上升沿检测,只在按键抬起瞬间为按键值,其他时刻全为0
  • key_old 保存上一次检测按键值

案例1:key1控制LED1开和关

注意点,书写规范。

  • 声明都在 *.h 文件中
  • Led_Disp() 和 KeyScan() 都涉及到 GPIO,那么就在 gpio.c 进行定义。
//gpio.h
/* USER CODE BEGIN Prototypes */
void Led_Disp(uint8_t ucled);
uint8_t Key_Scan(void);
/* USER CODE END Prototypes *///gpio.c
/* USER CODE BEGIN 2 */
void Led_Disp(uint8_t ucled)
{HAL_GPIO_WritePin(GPIOC,0xFF<<8,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);	// PD2 HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC,ucled<<8,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}uint8_t Key_Scan(void)
{uint8_t key_val=0;if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET){key_val=1;}if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET){key_val=2;}if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET){key_val=3;}if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET){key_val=4;}return key_val;
}
/* USER CODE END 2 *///main.h
/* USER CODE BEGIN EFP */
void Led_Proc(void);
void Key_Proc(void);
/* USER CODE END EFP *///main.c
/* USER CODE BEGIN PV */
uint8_t ucled=0x01;
uint8_t key_val,key_up,key_down,key_old;
/* USER CODE END PV */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */Led_Proc();Key_Proc();}/* USER CODE END 3 *//* USER CODE BEGIN 4 */
void Led_Proc(void){Led_Disp(ucled);
}
void Key_Proc(void){key_val = Key_Scan();key_down = key_val & (key_val ^ key_old);key_up = ~key_val & (key_val ^ key_old);key_old = key_val;if(key_down == 1){ucled ^= 0x01;}
}
/* USER CODE END 4 */

案例2:按键按下LED亮,松开LED灭

void Key_Proc(void){key_val=Key_Scan();key_down = key_val & (key_val^key_old);key_up = ~key_val & (key_val^key_old);key_old=key_val;if(key_down==3){ucled=0x01;//下降沿,按下LED亮}if(key_up==3){ucled=0x00;//上升沿,松开LED灭}
}

三、长按 短按

按键按下后开始计时,如果没有在规定时间内抬起,就是长按,否则就是短按。

  • 短按,LED1亮,LED2不亮
  • 长按,LED1灭,LED2亮
void Key_Proc(void){key_val=Key_Scan();key_down = key_val & (key_val^key_old);key_up = ~key_val & (key_val^key_old);key_old=key_val;if (key_down){uskey = 0; //按下就从0开始计时}if (uskey < 1000){if(key_up == 1){ //1s 内抬起,短按ucled = 0x01;}if(key_up == 2){// 按键2短按操作,自行填写}}else{if(key_val == 1){ //1s 后未抬起,长按ucled = 0x02;}if(key_up == 2){//按键2长按操作}}
}

这里的 uskey,出门右转 STM32点亮LED的系统定时器。

四、单击 双击

当按键抬起时,开始计时。

双击:当在规定时间内再次按下该按键;

单击:超时没有按键按下。

案例

双击B1,LED2亮,LED1灭

单击B1,LED1亮,LED2灭

void Key_Proc(void){key_val=Key_Scan();key_down = key_val & (key_val^key_old);key_up = ~key_val & (key_val^key_old);key_old=key_val;//抬手//第一次单击并抬手,要执行下面操作的 flag=0操作//第二次单击并抬手,要执行下面操作的 flag=1操作if(key_up){key_temp = key_up;  //记录此时的动作//flag初始值为0if(key_flag==0){  //开始计时uskey = 0;key_flag = 1;}else{  //双击结束key_flag = 0;}}if(key_flag==1){if(uskey<300){  //没超时if(key_down==1 && key_temp==1){ //双击B1,点亮灯2ucled = 0x02;}if(key_down==2 && key_temp==2){//双击B2}}else{if(key_temp==1){  //超时ucled = 0x01; //单击B1,亮灯1}if(key_temp==2){//单击B2}key_flag=0;}}
}

当按键抬起后,key_up会从按键值变0,需要有个临时变量 key_temp 保存按键值。那么双击可以定义为 key_temp=1 && key_down==n。

单击 双击,需要考虑下面3个问题:

  1. 上电后第一次按下
  2. 双击结束后的下一次
  3. 单击结束,超时后的第一次

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com