zoukankan      html  css  js  c++  java
  • stm32按键识别

    刚写了一个关于stm32单片机的按键识别的程序。目的,同时识别多个按键,并且不浪费cpu的时间。

    关于去抖动,以前以为是在按键的时候,手会抖动。通过程序验证,这个确实是误解。这个应该是防止意外干扰。以我的手按键的速度,单次持续时间小于0.2秒钟。

    前提:引脚低电平为按键按下。为每个按键设置3个变量,分别是识别过程的计数器keycnt、识别的结果keystat、可以判定的结果keymod(比如按下、释放、单击、双击、长按等)。

    本例 只有单击一种判断,keymod暂时不用。另外考虑,按键判定后,直到松开,不重复判定。具体模式和规则,可根据需要修改。另外要考虑,按键后,要执行的其他动作,是瞬间动作还是长时间动作,比如让灯闪烁,本例没有涉及该步骤。

    思路:定时周期内:扫描每个按键的引脚电平,根据预定规则改变对应的计数器;依据计数状态,给出按键结果。

    对于具体应用,应进一步人性化。

    部分头文件:

    // KEY:PB12,PB13,PB14,PB15;PB3,PB4
    // KEY On:0 ; KEY Off:1 低电平触发

    #ifndef __MINIKEY_

    #define __MINIKEY_

    #include "stdint.h"
    #include "miniled.h"
    #include "miniusart.h"
    #include "minirtc.h"

    #define keynum 6 //On Board KEY NUMBER

    #define KEY0 (GPIOB->IDR&0x1000) //PB12
    #define KEY1 (GPIOB->IDR&0x2000) //PB13,
    #define KEY2 (GPIOB->IDR&0x4000) //PB14
    #define KEY3 (GPIOB->IDR&0x8000) //PB15
    #define KEY4 (GPIOB->IDR&0x0001) //PB0
    #define KEY5 (GPIOB->IDR&0x0002) //PB1
    #define KEYON 0
    #define KEYOFF 1
    #define KEYPRESS 0x02  //单击

    #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,则为启动相应功能。

    // KEY:PB12,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);
    }
    }

  • 相关阅读:
    mysql 复制表数据,表结构的3种方法
    MySQL 存储过程使用表名做参数
    关于mysql engine(引擎)的疑问
    mysql存储过程之循环
    mysql 命令大全
    关于mysql的表名/字段名/字段值是否区分大小写的问题
    navicat for mysql 快捷键(原创)
    解决"Subquery returns more than 1 row"sql查询错误
    mysql:“Access denied for user 'root@IP地址'"
    MySQL常用经典语句
  • 原文地址:https://www.cnblogs.com/htsky/p/5919514.html
Copyright © 2011-2022 走看看