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; } |
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/) | Powered by Discuz! X3.4 |