你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】stm32按键识别

[复制链接]
STMCU小助手 发布时间:2022-2-5 23:00
刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。
关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。
前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。
本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。
思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。
对于具体应用,应进一步人性化。
部分头文件:
  1. // KEY:PB12,PB13,PB14,PB15;PB3,PB4
  2. // KEY On:0 ; KEY Off:1 低电平触发

  3. #ifndef __MINIKEY_

  4. #define __MINIKEY_

  5. #include "stdint.h"
  6. #include "miniled.h"
  7. #include "miniusart.h"
  8. #include "minirtc.h"

  9. #define keynum 6 //On Board KEY NUMBER

  10. #define KEY0 (GPIOB->IDR&0x1000) //PB12
  11. #define KEY1 (GPIOB->IDR&0x2000) //PB13,
  12. #define KEY2 (GPIOB->IDR&0x4000) //PB14
  13. #define KEY3 (GPIOB->IDR&0x8000) //PB15
  14. #define KEY4 (GPIOB->IDR&0x0001) //PB0
  15. #define KEY5 (GPIOB->IDR&0x0002) //PB1
  16. #define KEYON 0
  17. #define KEYOFF 1
  18. #define KEYPRESS 0x02  //单击

  19. #endif
复制代码

相关功能:
uint8_t keypress=15; // 去抖动参数,用于计数器参考判定按键单击。定时器间隔为0.01秒。
uint8_t keycnt[keynum]; //计数器
uint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;
uint8_t keymod[keynum]; //定义同keystat,对应bit位置1,则为启动相应功能。
// KEYB12,PB13,PB14,PB15
void key_init(void)
{
uint8_t m;
RCC->APB2ENR|=0x08; //enable PORTB clock
GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£
GPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15
GPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£
GPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
GPIOB->ODR&=0x0FF0;
GPIOB->ODR|=0xF00F;

for(m=0;m<keynum;m++){
keycnt[m]=0;
keystat[m]=0;
keymod[m]=0x10;
}
}
//循环扫描,在定时中执行
void keyscan(void)
{
    uint8_t k;
    for(k=0;k<keynum;k++){
        keyone(k);
    }
}
//识别规则
void keyone(uint8_t nkey)
{
switch(nkey){
case 0:
if(KEY0==KEYON){
    if(keycnt[nkey]==keypress){
     //   keycnt[nkey]=0;//长按视为反复触发按键。
        keystat[nkey]=0x02;
        }else{
        keycnt[nkey]++;
        }
}else{
     keycnt[nkey]=0;
}
break;
…………
}
//后续动作,在定时中执行
void keydo(void)
{
if(keystat[0]==0x02){
keystat[0]=0; //reset key after done
kset0();  //要执行的动作
}
……………………
if(keystat[5]==0x02){
keystat[5]=0; //reset key begin done
led_flush(2);
led_flush(3);
}
}

收藏 评论0 发布时间:2022-2-5 23:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版