• AD按键-矩阵按键-独立按键:


    原理:利用数组分压+AD采集;

    优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来);可备用作为AD基准输入。

    缺点:不能做成组合按键(或者电阻要精确选择);且离IO口越近优先级越高。按键的识别收到精度的影响(消兜:抖动时间几毫秒到几十毫秒,所以连续读4次(每次8ms)直到读到值都相同。按键的识别是靠AD值的容差范围而非具体的AD值来识别)。基准电压的获得(IO或TL431)

    参考http://www.ednchina.com/ART_46350_11_0_OA_6f4d5e96.HTM

    http://blog.sina.com.cn/s/blog_7a9b7c4c0100sohh.html

    http://wenku.baidu.com/link?url=-vUPz14ryQnsrXNIJdfbOn1qw1JsJqIFRG9VUhxbaGjy80GEzZz8judHw1WRubzAsb-KOUzGfZQ-zVpOKu2PVH-SvRerysWsd-F_kTzivwS

    --------------------------矩阵按键程序---------------------------------------------

    矩阵键盘是否接上拉电阻:网友说法对于哪些弱上拉驱动能力弱的准3态IO的需要加,为了抗干扰也需要加;否则就不需要加。

    /**************************************************************
    *按键的键值分布图:
    0 1 2 3
    4 5 6 7
    8 9 10 11
    12 13 14 15
    ***************************************************************/
    /**************************************************************
    * 功能:P3外接4×4按键, 按照查表法读出键值,使用时需要添加延时消抖动
    * 返回:按键值0~15/如无键按下, 返回16
    ***************************************************************/
    /*uchar keyscan(void)
    {
    uchar code K_Tab[4][4] = {
    0xee, 0xde, 0xbe, 0x7e, //扫描码为0xfe时(仅第一行为0)第一行4列4个按键可能按下时的值
    0xed, 0xdd, 0xbd, 0x7d, //扫描码为0xfd时(仅第二行为0)第二行4列4个按键可能按下时的值
    0xeb, 0xdb, 0xbb, 0x7b,
    0xe7, 0xd7, 0xb7, 0x77};
    uchar temp1 = 0xfe, temp2, i, j;
    for(i = 0; i < 4; i++)
    { //扫描低四位
    P3 = temp1; //输出一行0
    temp2 = P3; //马上就读入
    if((temp2 & 0xf0) != 0xf0) //如果有键按下
    {
    for(j = 0; j < 4; j++) //就扫描高四位
    if(temp2 == K_Tab[i][j]) //查表
    return i * 4 + j; //查到了就返回按键的数值
    }
    else temp1 = _crol_(temp1, 1);//非51的循环移位处理:(uchar)~(1<<i)
    }
    return 16; //没有查到,返回按键松开的代码
    } */ //呵呵,实质性的语句不过9行,就是这么简练!

    /**************************************************************
    * 功能: 按照反转计算法读出键值(IO必须是双向的或能切换),不用循环结构
    * 输出:按键值0~15/如无键按下, 返回16
    ***************************************************************/
    uchar keyscan(void)
    {
    uchar temH, temL,hang,lie;
    uchar key_value;
    P3 = 0xf0;
    if(P3 != 0xf0)
    {
    delay(5); //消抖
    if(P3 != 0xf0) //的确是有按键被按下
    {
    P3 = 0xf0; temH = P3; //低四位先输出0;读入,高四位含有按键信息
    P3 = 0x0f; temL = P3; //然后反转输出0;读入,低四位含有按键信息
    switch(temH) {
    case 0xe0: lie = 0; break;
    case 0xd0: lie = 1; break;
    case 0xb0: lie = 2; break;
    case 0x70: lie = 3; break;
    default: lie = 16;//按下的不是上述按键,就当是没有按键
    }
    switch(temL)
    {
    case 0x0e: hang = 0; break;
    case 0x0d: hang = 1; break;
    case 0x0b: hang = 2; break;
    case 0x07: hang = 3; break;;
    default: hang = 16;//按下的不是上述按键,就当是没有按键
    }
    retrun (hang -1)*4 + lie;
    }
    }
    }

    定时器的消抖法(裸奔程序):初始化keyvalue=一个不可能存在的值。

    1当有按键按下时(keyolder),启动定时器定时10MS(systick),然后退出;

    2定时到后置位Flag_10MS,并读按键值keynew

    3if((Flag_10MS)&&(keyoder==keynew)) keyvalue=keynew;

    4键值使用:

      if(keyvalue!=一个不可能存在的值)

      {

              ....

        }

     独立按键的经典算法:可以简洁的识别长按和短按,对于弹式按键和锁式按键都适合(锁式相当于长按)

    PB0表示第一个按键

    长按(2s):ReadData = 0x01;Trg = 0x00;Cont = 0x01;

    短按:ReadData = 0x01;Trg = 0x01;Cont = 0x01;

    无按键或弹起:ReadData = 0x00;Trg = 0x00;Cont = 0x00;

    http://blog.csdn.net/caiyunfreedom/article/details/6543256#comments

    核心算法

    unsigned char Trg;

    unsigned char Cont;

    void KeyRead( void )/*每20MS调用一次*/

    {

        unsigned char ReadData = PINB^0xff;   // 1

        Trg = ReadData & (ReadData ^ Cont);      // 2

        Cont = ReadData;                                // 3

    }

     单片机按键识别篇---单击---双击----长按:对按下和抬起都消抖,消抖后先记下按下的时间,如果按下的时间超过一定值说明为长按(长按累加重点是显示),;如果抬起后超过一定时间没有检测到再次按下则为单击否则为双击。

    http://www.cnblogs.com/UPUPDay2152/p/9673886.html 

    分享一个mini板按键KEY0单击、双击(连续返回2个相同的值)、长按和串口实现灯的控制状态

    http://www.openedv.com/forum.php?mod=viewthread&tid=274729&extra=

     

      unsigned char key_driver(void)
    {
        static unsigned char key_state = key_state_0, key_time = 0;
        unsigned char key_press, key_return = N_key;

        key_press = KEY0;                    // 读按键IO电平

        switch (key_state)
        {
          case key_state_0:                              // 按键初始态
            if (!key_press) key_state = key_state_1;      // 键被按下,状态转换到按键消抖和确认状态
            break;
           
          case key_state_1:                      // 按键消抖和确认状态
            if (!key_press)                      //按键仍然处于按下
            {
                 key_time = 0;                     
                 key_state = key_state_2;   //,消抖完成,状态转换到按下键时间的计时
            }
            else
                 key_state = key_state_0;   //按键已抬起,转换到按键初始态。此处完成和实现软件消抖,此时
            break;                          //按键的按下和释放都在此消抖
           
          case key_state_2:
            if(key_press)
            {
                 key_return = S_key;        // 此时按键的释放,说明是产生一次短操作,回送S_key
                 key_state = key_state_0;   // 转换到按键的初始态
            }
            else if (++key_time >= 100)     // 继续按下,计时10ms
            {
                 key_return = L_key;        // 按下时间>1000ms,此按键为长按操作,返回长按操作
                 key_state = key_state_3;   // 转换到等待按键释放状态
            }
            break;

          case key_state_3:                 // 等待按键释放状态,此状态只返回无按键事件
            if (key_press) key_state = key_state_0; //按键已释放,已转换到按键初始态
            break;
        }
        return key_return;
    }

    /*=============
    在定时器10ms中断中设立标志,在主程序中查询标志,到了就执行该操作(即10ms执行一次)
    ===============*/
    unsigned char key_read(void)
    {
          static unsigned char key_m = key_state_0, key_time_1 = 0;
        unsigned char key_return = N_key,key_temp;
        key_temp = key_driver();
         
        switch(key_m)
        {
            case key_state_0:
                if (key_temp == S_key )
                {
                     key_time_1 = 0;               // 第一次单击,不返回,到下个转态判断后面是否出现双击
                     key_m = key_state_1;
                }
                else
                     key_return = key_temp;        // 对于无键、长按,返回原事件
                break;

            case key_state_1:
                if (key_temp == S_key)             // 又一次单击(间隔时间<500ms)
                {
                     key_return = D_key;           // 返回双击键事件,回初始状态
                     key_m = key_state_0;
                }
                else                                
                {                                  // 这里500ms内肯定读到的都是无键事件,
                     if(++key_time_1 >= 50)        //因为长按>1000ms,低层返回都是无按键
                     {
                          key_return = S_key;      // 500ms内没有再次出现单键事件,返回上一次的单键
                          key_m = key_state_0;     // 返回初始状态
                     }
                 }
                 break;
        }
        return key_return;  
        }

     思考:外中断按键的消抖。

  • 相关阅读:
    Git commit 信息标准和丢弃必须要的commit
    Markdown list状态下插入代码
    INIT: vesion 2.88 booting
    I.MX6 support eMMC 5.0
    GitLab non-standard SSH port
    PenMount Touch显示鼠标指针驱动安装
    Android WebView remote debugging
    Android预安装可卸载程序
    jmeter(六)元件的作用域与执行顺序
    jmeter(五)JDBC Request
  • 原文地址:https://www.cnblogs.com/jieruishu/p/4520056.html
Copyright © 2020-2023  润新知