一种PC键盘的革命性设计
时间:09-25
来源:互联网
点击:
1 引言
当电脑上别的配件都跟着摩尔定律越来越时髦的时候,键盘总是显得比较落寞,而“掌心键”的问世则将传统PC键盘的设计引领至一个全新的领域。掌心键,是放在单手掌中使用,对应于五个手指各有一个多功能按键,并通过五指同时组合操作,从而实现字符的输入;自带有点阵显示屏,通过其指示各种操作状态,考虑到用户使用习惯和人体特征,掌心键的外形设计大小适中,适合大众人群的手形,不论男女,皆可轻松的一手掌握,独特的按键凹槽设计将使手指的放位倍感舒适,而且降低了对坐姿的要求,同时支持左右手互换使用,且保证长时间使用也不易感到疲劳。
2 系统结构及工作原理
掌心键是通过五指组合方式进行输入,共有25=32种组合,其中包括一种无任何键按下的组合,实际可用组合则为31种。为了设计中描述、编程方便,将五指对应一个5位二进制数的5个位,D4D3D2D1D0,母指对应D4位,食指对应D3位,中指对应D2位,无名指对应D1位,小指对应D0位,按下手指的位值为1,不按的位值为0,这样每次组合按键时产生了一个按键值n,将32种组合定义为Km(m=0…31)。
为了单手能方便输入PC键盘的所有按键,首先要将PC按键分集,分为数字集、小写字母集、大写字母集、标点符集、编辑键集、功能键集等,表2-1列出了部分键集详细说明;输入时先选键集,再输入字符。在任何状态下都将K31定义为集切换,然后按Kn(n=1…30)可选30种键集,再按键集下相应字符对应的Kn即可完成一个字符的输入。如果接下来的字符是同一个键集的,就不必再切换键集,直接输入即可,这样可提高输入速度。输入任一个字符最多按3次键,即先按集转换,再选子集,然后输入指定字符,大部分时间都只需一次按键即可。
子集中以字母集用键值KN最多,从K1到K26,所有子集中的K27、K28、K29、K30很少用到,当前统一定义成最常用的全局通用功能键,就如集切换K31;分别定义为K27:空格,K28:回删,K29:后移,K30:回车。为了方便使用,用户可以自己配置,重新定义以上键值的功能。
对于PC键上多个键组合操作的情况,这里设置一个本地KeepLock状态,有三个键处理该状态,KeepStart是进入KeepLock,KeepRep是保持此前按的所有键不松开,称为重复键组KeepGroup,其后每按一次键与KeepGroup组合一起发给PC,直到KeepEnd结束KeepLock状态。比如在文本编辑时,要选择光标后的两个字符,在PC上应按两次Shift+ArrowR,操作过程是:KeepStart、ShiftL、KeepRep、ArrowR、ArrowR、KeepEnd;如果要输入两次Ctrl+Alt+Del,过程是:KeepStart、CtrlL、AltL、KeepRep、Del、Del、KeepEnd。
3 硬件设计
掌心键系统硬件结构如图3-1所示。硬件以PHILIPS公司含ARM7核的LPC2114单片机为中心,具有背光、黑白128X64点阵LCD屏,五个独立式多功能按键,配有PS2接口。
图3-1系统硬件结构图
电源来自PS2键盘接口,或电池,5V电源经过LM1117-3.3和LM1117-1.8稳压后供给各部分电路。显示部分选用COG的128X64点阵黑白LCD液晶,以I/O方式接入LPC2114单片机,LCD用来提示各种状态,以及输入的信息,亦用于脱机录入的信息显示。MAX3232构成RS-232串行通信接口,实现掌心键与PC机之间资料相互传送。五个独立按键都以外部电平中断方式输入,没有按键时,系统进入节电状态,只有按键时系统才短时工作,在脱机状态下工作时,电池供电的节电问题显得非常重要。设置蜂鸣器是为了协助提示按键操作。而JTAG接口是保留给软件开发和升级时使用。
正确检测掌心键的按键操作是硬件设计的重点。普通按键检测时,可以用软件方法处理按键机械抖动问题,程序过滤按键前后20ms时间即可解决抖动。而掌心键是多个键组合按下实现单PC键,不但要对每个按键去抖动,还要解决多键同时按下的时间差问题。刚开始使用掌心键时,操作速度较慢,随着使用时间的延长,按键速度越来越快,这样就有一个熟练的过程。为此,将去抖动的时间设成可配置的,设为JitterTime,当有操作时,保持JitterTime时间键Kn没有变化,即认为是Kn,从一个Kn变为Km,也是用JitterTime时间去抖动,当Km=0时就表明没有任按键操作。JitterTime的范围从20ms到2000ms。
4 软件设计
软件以uCos实时嵌入式操作为核心,按功能分为多个任务,软件采用C语言编写,主要完成两部分功能,其一是本地按键和显示,其二是将按键变为PC键扫描码通过PS2接口送给PC机。软件结构如图4-1所示。
图4-1 系统软件结构
算法的关键是对按键值的处理。由于PC键盘中的每个键都具有通码(接下)和断码(松开),产生的键盘扫描码由多个字节组成,而掌心键是多次操作才能构成PC键盘的单次操作,所以在算法中要设置很多状态变量来记忆操作过程,在完成一个PC键操作后才通过PS2接口输出通码或断码。下面给出了详细的原码程序和注释。
首先说明以下重要的全局变量:
char KeySet; //存入子键集号,因为不同子集的Kn值代表不同的键
char KeyStatus; //记忆处理状态,在不同阶段Kn有不同的意义
char …….
函数KeyMessage( )将按键原始值分集处理,分集后的值调用函数KeySend( )保存或发送,函数KeySendOn( )发送通码的扫描码,而函数KeySendOff( )发送断码的扫描码。
void KeySend( unsigned char OnCode ) //发送通码
{ if( KeepLock==1){ //保存组合通码KeepGroup
KeepGroup[KeepPtr++] = OnCode;
return; //只保存,不发送
}
If(KeepLock==2)……..
KeySendOn( OnCode ); //发送通码的扫描码
}
void KeySendOn( unsigned char OnCode )
{ KeyOnCodeOff = 0; //设标志,要求发断码
KeyOnCode = OnCode;
//记忆通码,以便发相应断码
switch( KeyOnCode ){ //根据KeyOnCode发送通码
OnCode_A: Ps2Out(0x1C); break;
OnCode_ArrowR: Ps2Out(0xE0); Ps2Out(0x74); break;
……..}}
void KeySendOff( void ) //发送断码的扫描码
{ if( KeyOnCodeOff ) return; //没发过通码,所有没有断码
KeyOnCodeOff = 1; //防止连续发断码
switch( KeyOnCode){ //根据最后发送的通码KeyOnCode补发断码
OnCode_A: Ps2Out(0xF0); Ps2Out(0x1C);
………}}
void KeyMessage( unsigned char Kn) //Kn是原始按键值
{ if( Kn==31){ KeyStatus="1"; return; }
if( KeyStatus==1){ if(Kn != 0 ){ KeySet="Kn"; KeyStatus="2"; } return; }
if( KeyStatus==2){
if( Kn==0){ KeySendOff(); return; }
if( KeySet==1){
switch( Kn ){
1: CapsLock =! CapsLock; KeySend(OnCapsLock); break;
2: NumLock=! NumLock; KeySend(OnNumLock); break;
3: ScrollLock=!ScrollLock; KeySend(OnScrollLock); break;
………… //其它情况处理同上
}
return;
}
if(KeySet==2){ //处理数字 }
if(KeySet==3){ //处理字母 }
…………}}
当电脑上别的配件都跟着摩尔定律越来越时髦的时候,键盘总是显得比较落寞,而“掌心键”的问世则将传统PC键盘的设计引领至一个全新的领域。掌心键,是放在单手掌中使用,对应于五个手指各有一个多功能按键,并通过五指同时组合操作,从而实现字符的输入;自带有点阵显示屏,通过其指示各种操作状态,考虑到用户使用习惯和人体特征,掌心键的外形设计大小适中,适合大众人群的手形,不论男女,皆可轻松的一手掌握,独特的按键凹槽设计将使手指的放位倍感舒适,而且降低了对坐姿的要求,同时支持左右手互换使用,且保证长时间使用也不易感到疲劳。
2 系统结构及工作原理
掌心键是通过五指组合方式进行输入,共有25=32种组合,其中包括一种无任何键按下的组合,实际可用组合则为31种。为了设计中描述、编程方便,将五指对应一个5位二进制数的5个位,D4D3D2D1D0,母指对应D4位,食指对应D3位,中指对应D2位,无名指对应D1位,小指对应D0位,按下手指的位值为1,不按的位值为0,这样每次组合按键时产生了一个按键值n,将32种组合定义为Km(m=0…31)。
为了单手能方便输入PC键盘的所有按键,首先要将PC按键分集,分为数字集、小写字母集、大写字母集、标点符集、编辑键集、功能键集等,表2-1列出了部分键集详细说明;输入时先选键集,再输入字符。在任何状态下都将K31定义为集切换,然后按Kn(n=1…30)可选30种键集,再按键集下相应字符对应的Kn即可完成一个字符的输入。如果接下来的字符是同一个键集的,就不必再切换键集,直接输入即可,这样可提高输入速度。输入任一个字符最多按3次键,即先按集转换,再选子集,然后输入指定字符,大部分时间都只需一次按键即可。
子集中以字母集用键值KN最多,从K1到K26,所有子集中的K27、K28、K29、K30很少用到,当前统一定义成最常用的全局通用功能键,就如集切换K31;分别定义为K27:空格,K28:回删,K29:后移,K30:回车。为了方便使用,用户可以自己配置,重新定义以上键值的功能。
对于PC键上多个键组合操作的情况,这里设置一个本地KeepLock状态,有三个键处理该状态,KeepStart是进入KeepLock,KeepRep是保持此前按的所有键不松开,称为重复键组KeepGroup,其后每按一次键与KeepGroup组合一起发给PC,直到KeepEnd结束KeepLock状态。比如在文本编辑时,要选择光标后的两个字符,在PC上应按两次Shift+ArrowR,操作过程是:KeepStart、ShiftL、KeepRep、ArrowR、ArrowR、KeepEnd;如果要输入两次Ctrl+Alt+Del,过程是:KeepStart、CtrlL、AltL、KeepRep、Del、Del、KeepEnd。
3 硬件设计
掌心键系统硬件结构如图3-1所示。硬件以PHILIPS公司含ARM7核的LPC2114单片机为中心,具有背光、黑白128X64点阵LCD屏,五个独立式多功能按键,配有PS2接口。
图3-1系统硬件结构图
电源来自PS2键盘接口,或电池,5V电源经过LM1117-3.3和LM1117-1.8稳压后供给各部分电路。显示部分选用COG的128X64点阵黑白LCD液晶,以I/O方式接入LPC2114单片机,LCD用来提示各种状态,以及输入的信息,亦用于脱机录入的信息显示。MAX3232构成RS-232串行通信接口,实现掌心键与PC机之间资料相互传送。五个独立按键都以外部电平中断方式输入,没有按键时,系统进入节电状态,只有按键时系统才短时工作,在脱机状态下工作时,电池供电的节电问题显得非常重要。设置蜂鸣器是为了协助提示按键操作。而JTAG接口是保留给软件开发和升级时使用。
正确检测掌心键的按键操作是硬件设计的重点。普通按键检测时,可以用软件方法处理按键机械抖动问题,程序过滤按键前后20ms时间即可解决抖动。而掌心键是多个键组合按下实现单PC键,不但要对每个按键去抖动,还要解决多键同时按下的时间差问题。刚开始使用掌心键时,操作速度较慢,随着使用时间的延长,按键速度越来越快,这样就有一个熟练的过程。为此,将去抖动的时间设成可配置的,设为JitterTime,当有操作时,保持JitterTime时间键Kn没有变化,即认为是Kn,从一个Kn变为Km,也是用JitterTime时间去抖动,当Km=0时就表明没有任按键操作。JitterTime的范围从20ms到2000ms。
4 软件设计
软件以uCos实时嵌入式操作为核心,按功能分为多个任务,软件采用C语言编写,主要完成两部分功能,其一是本地按键和显示,其二是将按键变为PC键扫描码通过PS2接口送给PC机。软件结构如图4-1所示。
图4-1 系统软件结构
算法的关键是对按键值的处理。由于PC键盘中的每个键都具有通码(接下)和断码(松开),产生的键盘扫描码由多个字节组成,而掌心键是多次操作才能构成PC键盘的单次操作,所以在算法中要设置很多状态变量来记忆操作过程,在完成一个PC键操作后才通过PS2接口输出通码或断码。下面给出了详细的原码程序和注释。
首先说明以下重要的全局变量:
char KeySet; //存入子键集号,因为不同子集的Kn值代表不同的键
char KeyStatus; //记忆处理状态,在不同阶段Kn有不同的意义
char …….
函数KeyMessage( )将按键原始值分集处理,分集后的值调用函数KeySend( )保存或发送,函数KeySendOn( )发送通码的扫描码,而函数KeySendOff( )发送断码的扫描码。
void KeySend( unsigned char OnCode ) //发送通码
{ if( KeepLock==1){ //保存组合通码KeepGroup
KeepGroup[KeepPtr++] = OnCode;
return; //只保存,不发送
}
If(KeepLock==2)……..
KeySendOn( OnCode ); //发送通码的扫描码
}
void KeySendOn( unsigned char OnCode )
{ KeyOnCodeOff = 0; //设标志,要求发断码
KeyOnCode = OnCode;
//记忆通码,以便发相应断码
switch( KeyOnCode ){ //根据KeyOnCode发送通码
OnCode_A: Ps2Out(0x1C); break;
OnCode_ArrowR: Ps2Out(0xE0); Ps2Out(0x74); break;
……..}}
void KeySendOff( void ) //发送断码的扫描码
{ if( KeyOnCodeOff ) return; //没发过通码,所有没有断码
KeyOnCodeOff = 1; //防止连续发断码
switch( KeyOnCode){ //根据最后发送的通码KeyOnCode补发断码
OnCode_A: Ps2Out(0xF0); Ps2Out(0x1C);
………}}
void KeyMessage( unsigned char Kn) //Kn是原始按键值
{ if( Kn==31){ KeyStatus="1"; return; }
if( KeyStatus==1){ if(Kn != 0 ){ KeySet="Kn"; KeyStatus="2"; } return; }
if( KeyStatus==2){
if( Kn==0){ KeySendOff(); return; }
if( KeySet==1){
switch( Kn ){
1: CapsLock =! CapsLock; KeySend(OnCapsLock); break;
2: NumLock=! NumLock; KeySend(OnNumLock); break;
3: ScrollLock=!ScrollLock; KeySend(OnScrollLock); break;
………… //其它情况处理同上
}
return;
}
if(KeySet==2){ //处理数字 }
if(KeySet==3){ //处理字母 }
…………}}
- 数字电视条件接收卡SoC SM1658的硬件结构及实现方法(下)(09-07)
- 基于USB的通用无线传输接口设计(09-20)
- 用IXP网络处理器设计的数字家庭媒体中心系统 (02-12)
- 带有 DRM 功能的 Nexperia Flash 媒体播放器(02-15)
- ARM9平台下的CMOS图像传感器数据采集系统(07-20)
- 基于ARM的智能家居远程控制系统设计 (10-15)