手机键盘型复合按键处理漫谈
手机型键盘输入处理程序思路漫谈
先看原理图:
由与门输出到中断口,当有按键按下时,产生中断。
void vINT0(void) interrupt 0
{
if(b_KeyShock==0)
{
if(b_Introduce==0)
{
b_KeyScan=1; b_KeyShock=1;
}
}
else b_KeyShock=0;
if(b_KeyShock==1)
b_KillShock=1;
b_Introduce=0;
}
以上程序用于设定标志,关闭初始化介绍标志。
按键扫描思路如下:为了防止抖动干扰,在处理时先关闭外部中断,然后读取键值即可。
#include <at89x51.h>
#define SCANPORT P1
unsigned char uca_LineScan[4]={0xEF,0xDF,0xBF,0x7F};
unsigned char ucKeyScan()
{
unsigned char ucTemp=0;
unsigned char ucRow=0,ucLine=0;
EX0=0;
for(ucLine=0;ucLine<4;ucLine++)
{
SCANPORT=uca_LineScan[ucLine];
ucTemp=SCANPORT&0x0F;
if(ucTemp!=0x0F)
{
switch(ucTemp)
{
case 0x0E: ucRow=10;break;
case 0x0D: ucRow=20;break;
case 0x0B: ucRow=30;break;
case 0x07: ucRow=40;break;
default: ucRow=50;break;
}break;
}
}
SCANPORT=0x0F;
EX0=1;
return ucRow+ucLine+1;
}
获得键值以后,输入字母大小写,数字处理思路如下:
1、 数字处理程序:unsigned char ucGetNum(unsigned char ucKeyCode)
switch(ucKeyCode)
{
case 11:return '7';break;
case 12:return '8';break;
case 42:return '0';break;
default:break;
}
return 0xFF;
2、字母处理程序:unsigned char ucGetLetter(unsigned char ucKeyCode)
先查看大小写标志:根据大小写标志选择执行的程序:
unsigned char ucGetLetter(unsigned char ucKeyCode)
{
if(b_CapStatus==0)
return ucCapProc(ucKeyCode);
else
return ucSmallProc(ucKeyCode);
}这里注意,RETURN后面可以跟一个函数,因为调用函数后,返回的也是一个uchar值。
每一个键值代表着三个字母,这样需要在按键的时候,对按键次数进行计数,根据计数值来计算选择是第几个字母,程序如下:
unsigned char ucCapProc(unsigned char ucKeyCode)
{
switch(uc_ClickCount%3)
{
case 0:return ucCapOne(ucKeyCode);break;
case 1:return ucCapTwo(ucKeyCode);break;
case 2:return ucCapThree(ucKeyCode);break;
default:break;
}
return ' ';
}
如果按键次数为1,根据键值获得的按键值如下:
unsigned char ucCapOne(unsigned char ucKeyCode)
{
switch(ucKeyCode)
{
case 11:return 'A';break;
case 12:return 'D';break;
case 13:return 'G';break;
case 21:return 'J';break;
case 22:return 'M';break;
case 23:return 'P';break;
case 31:return 'S';break;
case 32:return 'V';break;
case 33:return 'Y';break;
default:break;
}
return 0xFF;
}
以上完成了数字与字母的处理函数,下面对其他功能按键进行处理。
键盘功能图如下:
先看清楚单个字母或者数字按键:先读取光标位置,然后根据光标位置清除该数组中的字符,然后向液晶发现写入空格命令即可。程序如下:
void vCleanOne()
{
if(uc_CharPointer>0)
{
uc_CharPointer--;
uca_CharBox[uc_CharPointer]=' ';
vWriteCMD(0xC0+uc_CharPointer);
vShowOneChar(' ');
vWriteCMD(0xC0+uc_CharPointer);
}
}
“清除所有”功能:思路同“清除单个”,程序如下:
void vCleanAll()
{
unsigned char ucCount;
for(ucCount=0;ucCount<uc_CharPointer;ucCount++)
uca_CharBox[ucCount]=' ';
uc_CharPointer=0;
vWriteCMD(0xC0);
vShowChar(" ");
vWriteCMD(0xC0);
}
添加一个字符:
没输完一行?继续往后输入。输完一行了?清空,从头再来……单个字符输入完成以后,清按键计数。一行输入完后,光标回到行首,清除所有,写入字符,清空数组。
void vCharAdd(unsigned char ucChar) {
unsigned char ucCount;
if(uc_CharPointer<16)
{
vWriteCMD(0xC0+uc_CharPointer);
vShowOneChar(ucChar);
uca_CharBox[uc_CharPointer]=ucChar;
uc_CharPointer++;
}
else
{ vWriteCMD(0xC1);
vShowChar(" ");
vWriteCMD(0xC0);
vShowOneChar(ucChar);
for(ucCount=1;ucCount<16;ucCount++)
uca_CharBox[ucCount]=' ';
uca_CharBox[0]=ucChar;
uc_CharPointer=1;
}
b_CleanClick=1;
uc_CleanCount=0;
}
数字与字母切换:通过标志来选择,标志在处理键值的时候设定,见下文。
unsigned char ucGetChar(unsigned char ucChar)
{
if(b_InputMode==0)
return ucGetNum(ucChar);
else
return ucGetLetter(ucChar);
}
字符处理函数(最终函数,用于主程序调用):
void vCharProcess(unsigned ucKeyCode)
{
if(b_InputMode==0) vCharAdd(ucGetChar(ucKeyCode));
else
{
if(ucKeyCode!=42)
{
if(uc_ClickCount==0)
{
vCharAdd(ucGetChar(ucKeyCode)); }
else
{
uc_CharPointer--;
vCharAdd(ucGetChar(ucKeyCode));
}
}
else
{
vShowOneChar('!'); //punc
uca_CharBox[uc_CharPointer++]='!';
}
}
b_CleanClick=1;
uc_CleanCount=0;
流程如下:
1、 根据模式选择:数字?:直接输入,否则
2、 键盘是叹号?:写入叹号,否则
3、 按键次数是一次?:直接输入字母,否则
4、 按键多次?光标前移,输出,也就是说代替原来输入。
5、 清除计数。
键码处理主程序:
void vKeyProcess(unsigned char ucKeyCode)
{
if(uc_KeyTemp==ucKeyCode)
{
if(uc_ClickCount<255)
uc_ClickCount++;
}
else
{
uc_KeyTemp=ucKeyCode;
uc_ClickCount=0;
}
switch(ucKeyCode)
{
case 14:
b_Introduce=1;
vIntroduce();
break;
case 24:
vCharAdd(' ');
break;
case 34:
if(b_InputMode==1)
{
b_CapStatus=~b_CapStatus;
if(b_CapStatus==0)
{
vWriteCMD(0x8E);
vShowOneChar('B');
vWriteCMD(0xC0+uc_CharPointer);
}
else
{
vWriteCMD(0x8E);
vShowOneChar('S');
vWriteCMD(0xC0+uc_CharPointer);
}
}
break;
case 41:
vCleanAll();
break;
case 43:
vCleanOne();
break;
case 44:
b_InputMode=~b_InputMode;
if(b_InputMode)
{
if(b_CapStatus==0)
{
vWriteCMD(0x8E);
vShowChar("BC");
vWriteCMD(0xC0+uc_CharPointer);
}
else
{
vWriteCMD(0x8E);
vShowChar("SC");
vWriteCMD(0xC0+uc_CharPointer);
}
}
else
{
vWriteCMD(0x8E);
vShowChar(" N");
vWriteCMD(0xC0+uc_CharPointer);
}
break;
default:
vCharProcess(ucKeyCode);
}
}
程序流程如下:
1、按键,是按一次还是多次?如果是按多次,则键值与原来temp中的内容是相同的。按一次?计数清零,处理按键。如果按多次,则按键次数加1。
2、根据键值,然后处理如下功能。
3、开介绍键。
4、输入空格键。
5、大小写切换:数字输入?直接退出,否则:模式取反,根据取反后的模式选择不同的函数,包括大小写输入时候在液晶上显示的标志“B”or“S”.同时,光标移到输入地址。
6、清空所有
7、清空单个
8、输入法切换:标志取反,根据标志判断:字母输入?大写OR小写?大写:液晶输入“BC”,然后光标移回。小写?“SC”,数字?“N”,然后跳出
9、否则,获得键码。
先看原理图:
![]() |
由与门输出到中断口,当有按键按下时,产生中断。
void vINT0(void) interrupt 0
{
if(b_KeyShock==0)
{
if(b_Introduce==0)
{
b_KeyScan=1; b_KeyShock=1;
}
}
else b_KeyShock=0;
if(b_KeyShock==1)
b_KillShock=1;
b_Introduce=0;
}
以上程序用于设定标志,关闭初始化介绍标志。
按键扫描思路如下:为了防止抖动干扰,在处理时先关闭外部中断,然后读取键值即可。
#include <at89x51.h>
#define SCANPORT P1
unsigned char uca_LineScan[4]={0xEF,0xDF,0xBF,0x7F};
unsigned char ucKeyScan()
{
unsigned char ucTemp=0;
unsigned char ucRow=0,ucLine=0;
EX0=0;
for(ucLine=0;ucLine<4;ucLine++)
{
SCANPORT=uca_LineScan[ucLine];
ucTemp=SCANPORT&0x0F;
if(ucTemp!=0x0F)
{
switch(ucTemp)
{
case 0x0E: ucRow=10;break;
case 0x0D: ucRow=20;break;
case 0x0B: ucRow=30;break;
case 0x07: ucRow=40;break;
default: ucRow=50;break;
}break;
}
}
SCANPORT=0x0F;
EX0=1;
return ucRow+ucLine+1;
}
获得键值以后,输入字母大小写,数字处理思路如下:
1、 数字处理程序:unsigned char ucGetNum(unsigned char ucKeyCode)
switch(ucKeyCode)
{
case 11:return '7';break;
case 12:return '8';break;
case 42:return '0';break;
default:break;
}
return 0xFF;
2、字母处理程序:unsigned char ucGetLetter(unsigned char ucKeyCode)
先查看大小写标志:根据大小写标志选择执行的程序:
unsigned char ucGetLetter(unsigned char ucKeyCode)
{
if(b_CapStatus==0)
return ucCapProc(ucKeyCode);
else
return ucSmallProc(ucKeyCode);
}这里注意,RETURN后面可以跟一个函数,因为调用函数后,返回的也是一个uchar值。
每一个键值代表着三个字母,这样需要在按键的时候,对按键次数进行计数,根据计数值来计算选择是第几个字母,程序如下:
unsigned char ucCapProc(unsigned char ucKeyCode)
{
switch(uc_ClickCount%3)
{
case 0:return ucCapOne(ucKeyCode);break;
case 1:return ucCapTwo(ucKeyCode);break;
case 2:return ucCapThree(ucKeyCode);break;
default:break;
}
return ' ';
}
如果按键次数为1,根据键值获得的按键值如下:
unsigned char ucCapOne(unsigned char ucKeyCode)
{
switch(ucKeyCode)
{
case 11:return 'A';break;
case 12:return 'D';break;
case 13:return 'G';break;
case 21:return 'J';break;
case 22:return 'M';break;
case 23:return 'P';break;
case 31:return 'S';break;
case 32:return 'V';break;
case 33:return 'Y';break;
default:break;
}
return 0xFF;
}
以上完成了数字与字母的处理函数,下面对其他功能按键进行处理。
键盘功能图如下:
![]() |
先看清楚单个字母或者数字按键:先读取光标位置,然后根据光标位置清除该数组中的字符,然后向液晶发现写入空格命令即可。程序如下:
void vCleanOne()
{
if(uc_CharPointer>0)
{
uc_CharPointer--;
uca_CharBox[uc_CharPointer]=' ';
vWriteCMD(0xC0+uc_CharPointer);
vShowOneChar(' ');
vWriteCMD(0xC0+uc_CharPointer);
}
}
“清除所有”功能:思路同“清除单个”,程序如下:
void vCleanAll()
{
unsigned char ucCount;
for(ucCount=0;ucCount<uc_CharPointer;ucCount++)
uca_CharBox[ucCount]=' ';
uc_CharPointer=0;
vWriteCMD(0xC0);
vShowChar(" ");
vWriteCMD(0xC0);
}
添加一个字符:
没输完一行?继续往后输入。输完一行了?清空,从头再来……单个字符输入完成以后,清按键计数。一行输入完后,光标回到行首,清除所有,写入字符,清空数组。
void vCharAdd(unsigned char ucChar) {
unsigned char ucCount;
if(uc_CharPointer<16)
{
vWriteCMD(0xC0+uc_CharPointer);
vShowOneChar(ucChar);
uca_CharBox[uc_CharPointer]=ucChar;
uc_CharPointer++;
}
else
{ vWriteCMD(0xC1);
vShowChar(" ");
vWriteCMD(0xC0);
vShowOneChar(ucChar);
for(ucCount=1;ucCount<16;ucCount++)
uca_CharBox[ucCount]=' ';
uca_CharBox[0]=ucChar;
uc_CharPointer=1;
}
b_CleanClick=1;
uc_CleanCount=0;
}
数字与字母切换:通过标志来选择,标志在处理键值的时候设定,见下文。
unsigned char ucGetChar(unsigned char ucChar)
{
if(b_InputMode==0)
return ucGetNum(ucChar);
else
return ucGetLetter(ucChar);
}
字符处理函数(最终函数,用于主程序调用):
void vCharProcess(unsigned ucKeyCode)
{
if(b_InputMode==0) vCharAdd(ucGetChar(ucKeyCode));
else
{
if(ucKeyCode!=42)
{
if(uc_ClickCount==0)
{
vCharAdd(ucGetChar(ucKeyCode)); }
else
{
uc_CharPointer--;
vCharAdd(ucGetChar(ucKeyCode));
}
}
else
{
vShowOneChar('!'); //punc
uca_CharBox[uc_CharPointer++]='!';
}
}
b_CleanClick=1;
uc_CleanCount=0;
流程如下:
1、 根据模式选择:数字?:直接输入,否则
2、 键盘是叹号?:写入叹号,否则
3、 按键次数是一次?:直接输入字母,否则
4、 按键多次?光标前移,输出,也就是说代替原来输入。
5、 清除计数。
键码处理主程序:
void vKeyProcess(unsigned char ucKeyCode)
{
if(uc_KeyTemp==ucKeyCode)
{
if(uc_ClickCount<255)
uc_ClickCount++;
}
else
{
uc_KeyTemp=ucKeyCode;
uc_ClickCount=0;
}
switch(ucKeyCode)
{
case 14:
b_Introduce=1;
vIntroduce();
break;
case 24:
vCharAdd(' ');
break;
case 34:
if(b_InputMode==1)
{
b_CapStatus=~b_CapStatus;
if(b_CapStatus==0)
{
vWriteCMD(0x8E);
vShowOneChar('B');
vWriteCMD(0xC0+uc_CharPointer);
}
else
{
vWriteCMD(0x8E);
vShowOneChar('S');
vWriteCMD(0xC0+uc_CharPointer);
}
}
break;
case 41:
vCleanAll();
break;
case 43:
vCleanOne();
break;
case 44:
b_InputMode=~b_InputMode;
if(b_InputMode)
{
if(b_CapStatus==0)
{
vWriteCMD(0x8E);
vShowChar("BC");
vWriteCMD(0xC0+uc_CharPointer);
}
else
{
vWriteCMD(0x8E);
vShowChar("SC");
vWriteCMD(0xC0+uc_CharPointer);
}
}
else
{
vWriteCMD(0x8E);
vShowChar(" N");
vWriteCMD(0xC0+uc_CharPointer);
}
break;
default:
vCharProcess(ucKeyCode);
}
}
程序流程如下:
1、按键,是按一次还是多次?如果是按多次,则键值与原来temp中的内容是相同的。按一次?计数清零,处理按键。如果按多次,则按键次数加1。
2、根据键值,然后处理如下功能。
3、开介绍键。
4、输入空格键。
5、大小写切换:数字输入?直接退出,否则:模式取反,根据取反后的模式选择不同的函数,包括大小写输入时候在液晶上显示的标志“B”or“S”.同时,光标移到输入地址。
6、清空所有
7、清空单个
8、输入法切换:标志取反,根据标志判断:字母输入?大写OR小写?大写:液晶输入“BC”,然后光标移回。小写?“SC”,数字?“N”,然后跳出
9、否则,获得键码。