|
综合坛内各种按键扫描方法,用仿真验证一个4线扫描65键的方案。适用于AVR、51或其它单片机。
特点:
1.外接二极管较少
2.键数可裁减
3.扫描逻辑简单
图中按键分为A~E区,可根据需要,裁减后部键区,以获得较少的二极管得到较多的键数。
A区:共10个键,无需增加二极管;
B区:共12个键,当系统需求11~22键时,选用A、B区,B区每增加1管,可增加3个键;
C区:共30个键,当系统需求23~40键时,选用A、C区,C区每增加2管,可增加5键,C区与B区不同时使用;
D区:共21个键,当系统需求41~61键时,选用A、C、D区,D区每增加1管,可增加1键;
E区:共4键,D区每增加3管,才可增加1键,不具实用价值,仅作测试用。
以上的各种组合方式,应该达到了4线的极限键数。一种两二极管串联下拉的组合方式可靠性不高,没在考范围内。
以下是仿真电路,按从左到右,从上到下方向,键号从1~65依次递增。用鼠标按下按键,带BCD译码的数码管即显示相应的键号。
扫键方法:
1.首次扫键,4线设为上拉输入,记录4位状态;
2.4线依次输出0,并记录其余三线状态;
3.完成上面5次扫描,刚好16位,一个整型变量可记录。
4.与预设的键码比较,得出相应键号。
程序/仿真文件打包于下,有兴趣的朋友可下载测试。
点击此处下载 ourdev_476451.rar(文件大小:78K) (原文件名:4-65key.rar)
(原文件名:4-65 key.PNG)
程序如下:
/*****************************************
Mega16 4线65键测试程序
CLK = 4MHz
by cowboy 2009/08/30
*****************************************/
//硬件连接:PA低4位接键盘,PC接显示口
#include <mega16.h>
#include <delay.h>
unsigned int key_buff;
unsigned char key_step;
unsigned char key_num;
const unsigned int key_tab[65]=
{
0x0900,0x0090,0x0009,0x0204,0x0420,0x0042,0x1124,0x2812,0x4481,0x8248, //A区键码
// 0x0800,0x0400,0x0200,0x0100,0x0080,0x0040,0x0020,0x0010,0x0008,0x0004,0x头0002,0x0001, //B区键码
0x0030,0x0006,0x3936,0x0800,0x0100,0x0c00,0x0003,0x6c93,0x0080,0x0010, //C区键码
0x0600,0x00c0,0xc6c9,0x0008,0x0001,0x0140,0x0028,0x936c,0x0004,0x0200,
0x0180,0x0005,0x55a5,0x0400,0x0020,0x0a00,0x0018,0xaa5a,0x0040,0x0002,
0x0024,0x0012,0x0802,0x0401,0x0480,0x0240,0x0048,0x0120,0x0104,0x0081,0x0810,0x0208, //D区键码
0x0e00,0x01c0,0x0038,0x0007,0xffff,0x0124,0x0812,0x0481,0x0248, //E区键码
0xeedb,0xd7ed,0xbb7e,0x7db7,
};
//================ 键盘扫描 ==================
unsigned char key_scan(void)
{
unsigned char i;
if(key_step == 0)
{ //首次扫描
key_buff = ~PINA & 0x0f; //读入4位状态
PORTA &= ~0x01;
DDRA |= 0x01; //置A口为输出0
key_step = 1; //切换到下一状态
return 0;
}
for(i=1;i!=0x10;i<<=1) //其余的4次扫描
{ //依次获取3个位的状态
if (key_step == i) continue;//当前主动扫描位,略过
key_buff <<= 1; //移出1空位
if ((i & PINA) == 0) key_buff |= 1; //读入1位
}
DDRA &= ~key_step; //置上一扫锚位为上拉输入
PORTA |= key_step;
key_step = (key_step & 0x07)<<1;//切换到下一状态
PORTA &= ~key_step; //置下一扫描位输出0
DDRA |= key_step;
if (key_step != 0) return 0; //若未完成,返回0
for (i=0;i<65;i++) if (key_buff == key_tab) break;//查找键号
if (i == 65) i=0; else i++; //0表示没按下或错键
if (i == key_num) return 1; //消抖,并返完成标志
key_num = i; //记录本次键号
return 0;
}
//================ 测试主程序 ================
void main(void)
{
PORTA = 0x0F;
DDRC = 0xFF;
while (1)
{
delay_ms(5);
if(key_scan() == 1) //若按键有效则以BCD码输出显示
PORTC = ((key_num/10)<<4) + key_num%10;
}
}
(原文件名:未命名.PNG)
使用提示:
1.当的使用较少量按键时,请将键码表数组长度相应减少,以节省代码空间和减少搜索时间;
2.当不需要57号以后的按键时,第一次的扫描步骤可省却,同时键码数组所有数据高4位清零;
3.鉴于AVR内部上拉电阻较大,为提高可靠性,可于四线各接一上拉电阻;
4.65个键码搜索时间较长(AVR@4MHz约0.4ms),改进方法可对键码按大小排序,然后按二分法进行6次比较即可识别键号;
5.若IO资源紧张,但需求按键较少(20以内),可考虑三线键盘。请参阅以前贴子。
参考资料:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1563031
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1600359
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=854599
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=2243715 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|