查看: 828|回复: 0
打印 上一主题 下一主题

4*4按键,状态机思想:定时扫描+多键组合+连_发功能

[复制链接]
跳转到指定楼层
沙发
发表于 2016-3-21 21:40:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1、该段程序是4*4键盘扫描程序,功能比较全,根据实际情况可在次基础上进行修改;
2、已调试通过,但没有优化;

/*********************************************************************
文件:scankey.c
用途:通用4*4按键接口驱动程序
注意:
创建:2008.5.15
修改:2008.5.15
设计:raosibin
版本:ver1.3
功能说明:每隔10MS调用一次 ,实现了组合按键功能;连_发功能   
**********************************************************************/
#include "..\config.h"

/*********************************************************************
       COL0 COL1 COL2 COL3
* ROW4   0    1    2    3
* ROW5   4    5    6    7
* ROW6   8    9    A    B
* ROW7   C    D    E    F
*
* 普通按键:
* 2~E:数字按键
*
* 连_发按键:
* 0:
* 1:
*   
* 组合按键
* F  : 引导键
* F+0:
* F+1:
* 状态机思路
* F为组合引导键
* 每10MS扫描一次键盘  

* 状态0:检测是否有键按下;  
* 状态1:消抖处理  
* 状态2:确认按键,同状态1比较,除F引导键外相同则返回键值,
*       F引导键未按下转状态3;F引导键按下转状态5;  
* 状态3:计数1,(按3S,连_发判断);  
* 状态4:计数2,连_发功能

* 状态5:500MS内检测是否有F引导键+其他键按下;有转状态6,没有转状态8
* 状态6:消抖处理
* 状态7:同状态6比较,确认组合按键,返回组合键值,转状态3
* 状态8:消抖处理
* 状态9:先导键为单按键,返键值,转状态3.
**********************************************************************/
//按键初始化
void key_board_int1(void)
{
KEY_DDR_ROW   |=  KEY_ROW_ALL;                                                              //行输出,
KEY_PORT_ROW  &=~ KEY_ROW_ALL;
KEY_DDR_COL   &=~ KEY_COL_ALL;                                                              //列输入,并使能内部上拉
KEY_PORT_COL  |=  KEY_COL_ALL;
}

void key_board_int2(void)                                                                             //翻转初始化
{
KEY_DDR_ROW   &=~ KEY_ROW_ALL;                                                              //行输入,并使能内部上拉
KEY_PORT_ROW  |=  KEY_ROW_ALL;
KEY_DDR_COL   |=  KEY_COL_ALL;                                                              //列输出;
KEY_PORT_COL  &=~ KEY_COL_ALL;
}

unsigned char key_board_scan(void)
{
        unsigned key_value_buf;
        key_board_int1();
        KEY_PORT_ROW &=~ KEY_ROW_ALL;                                                        // 必须送2次!!!
        key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL;                                           // 读列电平
                                    
        key_board_int2();                                                                          // 翻转扫描
        KEY_PORT_COL  &=~ KEY_COL_ALL;
        key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW;                                              // 读行电平,并同翻转前的结果或
        return key_value_buf;
}

char read_keyboard()
{        
static char key_state = 0,  key_value1,key_value2,key_value3,key_value4,key_value5;
static char key_value6,key_value7,key_value8,key_value9;
static unsigned int key_time = 0;
char key_return = No_key;

        switch (key_state)
        {
                case 0:                                                                         // 判断是否有键按下
                        if (key_board_scan() != No_key)
                        {
                                key_state = 1;                                           // 有按键
                                break;                                                 // 转消抖确认状态
                        }
                        break;
                        
                case 1:                                                                         // 消抖处理
                        if (++key_time >= 1)                                                  // 改变判断条件可改变键盘灵敏度
                                {           
                            key_value1 = key_board_scan();
                            if (key_value1 != No_key)
                                    {
                                            key_state = 2;
                                            break;
                                    }
                            key_state = 0;
                            break;
                    }
                    break;
                    
             case 2:                                                                              // 确认按键,同状态1比较
                  key_value2 = key_board_scan();                                                         
                if (key_value2 == key_value1)                                                  // 再次扫描,
                        {        
                                if (key_value2 != 0b01110111)                          // 是否为引导键F,是则转状态5
                                  {
                                    switch (key_value2)                                       // 与状态1的相同,确认按键
                                    {                                             // 键盘编码,返回编码值
                                            case 0b11101110:
                                                    key_return = K1_1;                // 0;
                                                    break;
                                            case 0b11101101:
                                                    key_return = K1_2;                // 1
                                                    break;
                                             case 0b11101011:
                                                    key_return = K1_3;
                                                    break;
                                             case 0b11100111:
                                                    key_return = K1_4;
                                                    break;
                                             case 0b11011110:
                                                    key_return = K2_1;
                                                    break;
                                            case 0b11011101:
                                                    key_return = K2_2;
                                                    break;
                                             case 0b11011011:
                                                    key_return = K2_3;
                                                    break;
                                             case 0b11010111:
                                                    key_return = K2_4;
                                                    break;
                                            case 0b10111110:
                                                    key_return = K3_1;
                                                    break;
                                             case 0b10111101:
                                                    key_return = K3_2;
                                                    break;
                                             case 0b10111011:
                                                    key_return = K3_3;
                                                    break;
                                            case 0b10110111:
                                                    key_return = K3_4;
                                                    break;
                        case 0b01111110:
                                                    key_return = K4_1;
                                                    break;
                                             case 0b01111101:
                                                    key_return = K4_2;
                                                    break;
                                             case 0b01111011:
                                                    key_return = K4_3;
                                                    break;
                       default:
                       break;
                                     }
                                     key_state = 3;                                                // 转入等待按键释放状态
                                     key_time = 0;                                                       // 清0按键时间计数器
                                         break;
                              }
                                else
                                {
                            key_state = 5;
                                key_time = 0;
                            break;
                                }
                }               
                        else
                                key_state = 0;                                                // 两次列电平不同返回状态0,(消抖处理)
                    break;        
                                                        
        case 3:                                                                                   // 计数1,(按3S,连_发判断)                  
                key_value3 = key_board_scan();               
                if ( key_value3 == No_key)
                        key_state=0;                                                    // 按键已释放,转换到按键初始态
                        else if ((key_value3 == 0b11100111)||(key_value3 == 0b11011110))          // 改变此判断条件,可以确定
                          {                                                                       // 哪些键具备加速功能,3,4加速
                            if (++key_time >= 300)                                               // 按键时间计数
                              {
                                    key_state = 4;                                                  // 按下时间>3s,状态转换到计时2
                                    key_time = 0;                                                 // 清按键计数器
                                    key_return = KJ;                                             // 输出“18”
                              }
                        break;
                          }
                break;
                        
        case 4:                                                                                         // 计数2,连_发功能           
           key_value4 = key_board_scan();                  
           if ( key_value4 == No_key)
                        key_state=0;                                                     // 按键已释放,转换到按键初始态
                        else if (++key_time >= 20)                                                // 按键时间计数
                        {
                                key_time = 0;                                                 // 清按键计数器
                                key_return = KJ;                                             // 输出“18”
                                break;
                        }
          break;
         
        case 5:                                                               // 检测是否有F引导键+其他键按下;有转状态6,没有转状态8
    key_value5 = key_board_scan();           
    if (key_value5 == key_value2)
            {
              if (++key_time >= 50)                                               // 500MS到了吗?未到,状态5,不断扫描,到了,状态8
                      {
                              key_state = 8;
                              key_time = 0;
                              break;
                      }
                        break;
            }
        else
                {
            key_state = 6;
                break;
                }
                break;
        case 6:                                                               // 消抖处理
                key_value6 = key_board_scan();
                key_state = 7;
                break;
        case 7:                                                              // 同状态6比较,确认组合按键,返回组合键值,转状态3
                key_value7 = key_board_scan();
                if (key_value7 == key_value6)
                        {
                          switch (key_value7)
                          {
                                  case 0b01100110:
                                    key_return = KF_0;                   // 组合按键F+0
                                    break;
                        case 0b01100101:
                              key_return = KF_1;                           // 组合按键F+1
                                    break;               
                    }
                    key_state = 3;
      }
                break;
        case 8:                                                            //  消抖处理
                key_value8 = key_board_scan();
                key_state = 9;
                break;        
        case 9:                                                             // 同状态8比较,确认单按键,返键值,转状态3
                key_value9 = key_board_scan();
            if (key_value9 == key_value8)
            {
                    key_return = K4_4;
                    key_state = 3;
                    break;
            }
            key_state = 0;
                  break;
  default:
    break;
}
return key_return;
}




本资料转载于他站、仅供同学学习使用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表