最简单矩阵键盘扫描程序
key:mov p0,#00001111b;上四位和下四位分别为行和列,所以送出高
低电压检查有没有按键按下
jmp k10;跳到K10处开始扫描,这里可以改成其它条件转移指令来决
定本次扫描是否要继续,例如减1为0转移或者位为1或0才转移,这主
要用来增加功能,确认上一按键功能是否完成?是否相当于经过了延
时?是否要封锁键盘?
goend:jmp kend;如果上面判断本次不执行键盘扫描程序,则立即转
到程序尾部,不要浪费CPU的时间
k10:jb p0.0,k20;扫描正式开始,先检查列1四个键是否有键按下,
如果没有,则跳到K20检查列2
k11:mov p0,#11101111b;列1有键按下时,P0.0变低,到底是那一个键
按下?现在分别输出各行低电平
jb p0.0,k12;该行的键不按下时,p0.0为高电平,跳到到K12,检查其
它的行
mov r1,#1;如果正好是这行的键按下,将寄存器R0写下1,表示1号键
按下了
k12:mov p0,#11011111b
jb p0.0,k13
mov r1,#2;如果正好是这行的键按下,将寄存器R0写下2,表示2号键
按下了
k13:mov p0,#10111111b
jb p0.0,k14
mov r1,#3;如果正好是这行的键按下,将寄存器R0写下3,表示3号键
按下了
k14:mov p0,#01111111b
jb p0.0,kend;如果现在四个键都没有按下,可能按键松开或干扰,
退出扫描(以后相同)
mov r1,#4如果正好是这行的键按下,将寄存器R0写下4,表示4号键
按下了
jmp kend;已经找到按下的键,跳到结尾吧
k20:jb p0.1,k30;列2检查为高电平再检查列3、4
k21:mov p0,#11101111b;列2有健按下时,P0.0会变低,到底是那一
行的键按下呢?分别输出行的低电平
jb p0.1,k22;该行的键不按下时p0.0为高电平,跳到到K22,检查另
外三行
mov r1,#5;如果正好是这行的键按下,将寄存器R0写下5,表示5号键
按下了(以后相同,不再重复了)
k22:mov p0,#11011111b
jb p0.1,k23
mov r1,#6
k23:mov p0,#10111111b
jb p0.1,k24
mov r1,#7
k24:mov p0,#01111111b
jb p0.1,kend
mov r1,#8
jmp kend;已经找到按下的键,跳到结尾吧(以后相同,不要重复了
)
k30:jb p0.2,k40
k31:mov p0,#11101111b
jb p0.2,k32
mov r1,#9
k32:mov p0,#11011111b
jb p0.2,k33
mov r1,#10
k33:mov p0,#10111111b
jb p0.2,k34
mov r1,#11
k34:mov p0,#01111111b
jb p0.2,kend
mov r1,#12
jmp kend
k40:jb p0.3,kend
k41:mov p0,#11101111b
jb p0.3,k42
mov r1,#13
k42:mov p0,#11011111b
jb p0.3,k43
mov r1,#14
k43:mov p0,#10111111b
jb p0.3,k44
mov r1,#15
k44:mov p0,#01111111b
jb p0.3,kend
mov r1,#16
kend: ret
行列扫描键盘可检测出双键按下
#include
#define ulong unsigned long
#define uint unsigned int
#define uchar unsigned char
extern void delay(unsigned int x);
unsigned char Tab_key[]= //行列式键盘映射
{0x00, //无键按下
7,8,9,/,
4,5,6,*,
1,2,3,-,
C,0,=,+,
//下面为按C同时再按的键:
7,8,9,/,
4,5,6,*,
1,2,3,-,
0,=,+,};
// P1口行列式键盘 //
#define KEYPIN_L P1 // 定义键扫描列端口为 P1
低四位输入 //
#define KEYPIN_H P1 // 定义键扫描行端口为 P1高
四位扫描输出 //
// P1口行列式键盘 //
//公用函数
unsigned char KeysCAN(void); // 键扫描函数 //
//内部私有函数
unsigned char fnKeycode(unsigned char key); // 根据键盘
映射表输出顺序键值 //
/*
// P1口行列式键盘 //
extern unsigned char KeysCAN(void); // 键扫描函数
//
*/
// P1口行列式键盘 //
//---------------------------------------------------------
------------------//
unsigned char KeysCAN(void) // 键扫描
函数 //
{
unsigned char sccode,recode,keytemp = 0;
KEYPIN_L = KEYPIN_L|0x0f; // P1低四
位为列线输入 //
KEYPIN_H = KEYPIN_H&0x0f; // P1高四
位为行线发全零扫描码 //
if ((KEYPIN_L&0x0f) != 0x0f)
{
delay(10); // 延时
10 MS 消抖 //
if ((KEYPIN_L&0x0f) != 0x0f)
{
sccode = 0xef; // 逐行扫
描码初值(1110 1111) //
while(sccode != 0xff) //将扫描4次
,keytemp为每次键值相 或的值 //
{
KEYPIN_H = sccode; // 输出
行扫描码 //
if ((KEYPIN_L&0x0f) != 0x0f) // 本行有
键按下 //
{
recode = (KEYPIN_L&0x0f)|0xf0; // 只
要低位,高位置1 //
keytemp |= (~sccode)+(~recode); //特
征码(高位为列P3,低位为行KEYPIN_H) //
}
sccode = (sccode << 1)|0x01; // 扫描码0
向高位移动 //
}
}
}
KEYPIN_H = KEYPIN_H|0xf0;
return(fnKeycode(keytemp));
}
//---------------------------------------------------------
------------------//
unsigned char fnKeycode(unsigned char key) // 根据键盘
映射表输出顺序键值 //
{
switch(key)
{
case 0x11: // 1 键 //
key = 0x01;
break;
case 0x21: // 2 键 //
key = 0x02;
break;
case 0x41: // 3 键 //
key = 0x03;
break;
case 0x81: // 4 键 //
key = 0x04;
break;
case 0x12: // 5 键 //
key = 0x05;
break;
case 0x22: // 6 键 //
key = 0x06;
break;
case 0x42: // 7 键 //
key = 0x07;
break;
case 0x82: // 8 键 //
key = 0x08;
break;
case 0x14: // 9 键 //
key = 0x09;
break;
case 0x24: // 10 键 //
key = 0x0A;
break;
case 0x44: // 11 键 //
key = 0x0B;
break;
case 0x84: // 12 键 //
key = 0x0C;
break;
case 0x18: // 13 键 //
key = 0x0D;
break;
case 0x28: // 14 键 //
key = 0x0E;
break;
case 0x48: // 15 键 //
key = 0x0F;
break;
case 0x88: // 16 键 //
key = 0x10;
break;
//以下为功能键//
case 0x19: // C +1 键 //
key = 0x11;
break;
case 0x29: // C +2 键 //
key = 0x12;
break;
case 0x49: // C +3 键 //
key = 0x13;
break;
case 0x89: // C +4 键 //
key = 0x14;
break;
case 0x1A: // C +5 键 //
key = 0x15;
break;
case 0x2A: // C +6 键 //
key = 0x16;
break;
case 0x4A: // C +7 键 //
key = 0x17;
break;
case 0x8A: // C +8 键 //
key = 0x18;
break;
case 0x1C: // C +9 键 //
key = 0x19;
break;
case 0x2C: // C +10 键 //
key = 0x1A;
break;
case 0x4C: // C +11 键 //
key = 0x1B;
break;
case 0x8C: // C +12 键 //
key = 0x1C;
break;
// case 0x18: // C +13 键 //
// key = 0x1D;
// break;
case 0x38: // C +14 键 //
key = 0x1D;
break;
case 0x58: // C +15 键 //
key = 0x1E;
break;
case 0x98: // C +16 键 //
key = 0x1F;
break;
default : // 无键 //
key = 0x00;
break;
}
return(Tab_key[key]);
}
矩键查寻键值44程序与显示
#include
//#include
#include
#define uchar unsigned char
#define TURE 1
#define FALSE 0
int key;
int del;
void Tkey(void);
void led(void);
/************主 程序*************/
void main(void)
{
void tkey(void);
void led(void);
void delay(int);
SCON=0x00;
TI=0;
while(TURE)
{
Tkey();
led();
delay(2000);
}
}
/********矩键查寻键值4*4程序******/按键为P1.0---P1.7
void Tkey(void)
{
uchar readkey;//rereadkey;
uchar x_temp,y_temp;
P1=0x0f;
x_temp=P1&0x0f;
if(x_temp==0x0f) goto keyout;
P1=0xf0;
y_temp=P1&0xf0;
readkey=x_temp|y_temp;
readkey=~readkey;
switch(readkey)
{
case 0x11:key=0; break;
case 0x21:key=1; break;
case 0x41:key=2; break;
case 0x81:key=3; break;
case 0x12:key=4; break;
case 0x22:key=5; break;
case 0x42:key=6; break;
case 0x82:key=7; break;
case 0x14:key=8; break;
case 0x24:key=9; break;
case 0x44:key=10;break;
case 0x84:key=11;break;
case 0x18:key=12;break;
case 0x28:key=13;break;
case 0x48:key=14;break;
case 0x88:key=15;break;
default: key=16;break;
}
keyout:_nop_();
}
/************显示程序*************/
void led(void)
{uchar code LEDValue[]=
{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0-9
uchar data num[6];
uchar k;
num[0]=0;
num[1]=0;
num[2]=0;
num[3]=0;
num[4]=key/10;
num[5]=key-(key/10)*10;
for(k=0;k<=5;k++)
{
SBUF=LEDValue[num[5-k]];
while(TI==0);
TI=0;
}
}
/************延时程序*************/
void delay(del)
{
for(del;del>0;del--);
}
;伪定义
KEYBUF EQU 30H ;键值暂存单元,查表时用
;*************************************
;* *
;* 主程序和中断程序入口 *
;* *
;*************************************
ORG 0000H ;程序执行开始地址
AJMP MAIN ;跳至MAIN执行
;*************************************
;* *
;* 主 程 序 *
;* *
;*************************************
ORG 0040H
MAIN: MOV P1,#0FFH
MOV P3,#0FFH
LCALL KEYSCAN ;主体程序。调用查键子程序
LJMP MAIN ;转MAIN循环
NOP ;软件陷阱
NOP
NOP
LJMP MAIN
;*************************************
;* *
;* 键盘工作子程序(4 * 5 阵列) *
;* 接口为2051的P3和P1口 *
;*************************************
KEYSCAN:MOV P3,#0FFH ;清P3口,初始化键低电平有效
CLR P3.2 ;清P3.2口
MOV A,P1 ;读P1口状态
ANL A,#0FH ;清高4位,保留低四位低电平有效
XRL A,#0FH ;异或相同则为0不同结果为1,为0则表;示无键被按下(这一行)
JZ NOKEY1 ;为0则转下一行键值处理
LCALL DL10MS ;有键按下则延时10ms再测一次抗干扰
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY1 ;是干扰则转下一行键值处理程序
MOV A,P1
ANL A,#0FH ;保留低四?
KB1: CJNE A,#0EH,KB2 ;如果值为#0E则为P1.4与P1.0组合的键
MOV KEYBUF,#0 ;赋键值
LJMP KEYWORK ;转键处理
KB2: CJNE A,#0DH,KB3 ;如果值为#0D则为P1.4与P1.1组合的键
MOV KEYBUF,#1
LJMP KEYWORK
KB3: CJNE A,#0BH,KB4 ;如果值为#0B则为P1.4与P1.2组合的
MOV KEYBUF,#2
LJMP KEYWORK
KB4: CJNE A,#07H,KB5 ;如果值为#07则为P1.4与P1.3组合的
MOV KEYBUF,#3
LJMP KEYWORK
KB5: NOP
;
NOKEY1: MOV P3,#0FFH
CLR P3.3
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY2
LCALL DL10MS
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY2
MOV A,P1
ANL A,#0FH
CJNE A,#0EH,KB6
MOV KEYBUF,#4
LJMP KEYWORK
KB6: CJNE A,#0DH,KB7
MOV KEYBUF,#5
LJMP KEYWORK
KB7: CJNE A,#0BH,KB8
MOV KEYBUF,#6
LJMP KEYWORK
KB8: CJNE A,#07H,KB9
MOV KEYBUF,#7
LJMP KEYWORK
KB9: NOP
;
NOKEY2: MOV P3,#0FFH
CLR P3.4
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY3
LCALL DL10MS
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY3
MOV A,P1
ANL A,#0FH
CJNE A,#0EH,KB10
MOV KEYBUF,#8
LJMP KEYWORK
KB10: CJNE A,#0DH,KB11
MOV KEYBUF,#9
LJMP KEYWORK
KB11: CJNE A,#0BH,KB12
MOV KEYBUF,#10
LJMP KEYWORK
KB12: CJNE A,#07H,KB13
MOV KEYBUF,#11
LJMP KEYWORK
KB13: NOP
;
NOKEY3: MOV P3,#0FFH
CLR P3.5
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY4
LCALL DL10MS
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY4
MOV A,P1
ANL A,#0FH
CJNE A,#0EH,KB14
MOV KEYBUF,#12
LJMP KEYWORK
KB14: CJNE A,#0DH,KB15
MOV KEYBUF,#13
LJMP KEYWORK
KB15: CJNE A,#0BH,KB16
MOV KEYBUF,#14
LJMP KEYWORK
KB16: CJNE A,#07H,KB17
MOV KEYBUF,#15
LJMP KEYWORK
KB17: NOP
;
NOKEY4: MOV P3,#0FFH
CLR P3.7
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY5
LCALL DL10MS
MOV A,P1
ANL A,#0FH
XRL A,#0FH
JZ NOKEY5
MOV A,P1
ANL A,#0FH
CJNE A,#0EH,KB18
MOV KEYBUF,#16
LJMP KEYWORK
KB18: CJNE A,#0DH,KB19
MOV KEYBUF,#17
LJMP KEYWORK
KB19: CJNE A,#0BH,KB20
MOV KEYBUF,#18
LJMP KEYWORK
KB20: CJNE A,#07H,KB21
MOV KEYBUF,#19
LJMP KEYWORK
KB21: NOP
;
NOKEY5: LJMP MAIN
;
KEYWORK:MOV A,KEYBUF ;得到键值
MOV DPTR,#TABLE
MOVC A,@A+DPTR ;查行键值送ACC
MOV P0,A
;
WAITFREE:
MOV A,P1 ;以下程序等待键释放
MOV KEYBUF,#00H
ANL A,#0FH
XRL A,#0FH
JNZ WAITFREE
RET
;
;*************************************
;* *
;* 延时513 us *
;* *
;*************************************
;
;513微秒延时程序
DELAY: MOV R2,#0FEH
DELAY1: DJNZ R2,DELAY1
RET
;
;*************************************
;* *
;* 延时10ms *
;* *
;*************************************
;
;10毫秒延时程序
DL10MS: MOV R3,#14H
DL10MS1:LCALL DELAY
DJNZ R3,DL10MS1
RET
;
TABLE: ;七段显示器数据定义
DB 0C0H, 0F9H, 0A4H, 0B0H, 99H ; 01234
DB 92H, 82H, 0F8H, 80H, 90H ; 56789
DB 88H, 83H, 0C6H, 0A1H, 86H; ABCDE
DB 8EH ; F
;
END ;程序结束
KEYBUF EQU 30H
ORG 00H
START: MOV KEYBUF,#2
WAIT:
MOV P3,#0FFH
CLR P3.4
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY1
LCALL DELY10MS
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY1
MOV A,P3
ANL A,#0FH
CJNE A,#0EH,NK1
MOV KEYBUF,#0
LJMP DK1
NK1: CJNE A,#0DH,NK2
MOV KEYBUF,#1
LJMP DK1
NK2: CJNE A,#0BH,NK3
MOV KEYBUF,#2
LJMP DK1
NK3: CJNE A,#07H,NK4
MOV KEYBUF,#3
LJMP DK1
NK4: NOP
DK1:
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
DK1A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ DK1A
NOKEY1:
MOV P3,#0FFH
CLR P3.5
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY2
LCALL DELY10MS
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY2
MOV A,P3
ANL A,#0FH
CJNE A,#0EH,NK5
MOV KEYBUF,#4
LJMP DK2
NK5: CJNE A,#0DH,NK6
MOV KEYBUF,#5
LJMP DK2
NK6: CJNE A,#0BH,NK7
MOV KEYBUF,#6
LJMP DK2
NK7: CJNE A,#07H,NK8
MOV KEYBUF,#7
LJMP DK2
NK8: NOP
DK2:
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
DK2A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ DK2A
NOKEY2:
MOV P3,#0FFH
CLR P3.6
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY3
LCALL DELY10MS
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY3
MOV A,P3
ANL A,#0FH
CJNE A,#0EH,NK9
MOV KEYBUF,#8
LJMP DK3
NK9: CJNE A,#0DH,NK10
MOV KEYBUF,#9
LJMP DK3
NK10: CJNE A,#0BH,NK11
MOV KEYBUF,#10
LJMP DK3
NK11: CJNE A,#07H,NK12
MOV KEYBUF,#11
LJMP DK3
NK12: NOP
DK3:
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
DK3A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ DK3A
NOKEY3:
MOV P3,#0FFH
CLR P3.7
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY4
LCALL DELY10MS
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY4
MOV A,P3
ANL A,#0FH
CJNE A,#0EH,NK13
MOV KEYBUF,#12
LJMP DK4
NK13: CJNE A,#0DH,NK14
MOV KEYBUF,#13
LJMP DK4
NK14: CJNE A,#0BH,NK15
MOV KEYBUF,#14
LJMP DK4
NK15: CJNE A,#07H,NK16
MOV KEYBUF,#15
LJMP DK4
NK16: NOP
DK4:
MOV A,KEYBUF
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P0,A
DK4A: MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ DK4A
NOKEY4:
LJMP WAIT
DELY10MS:
MOV R6,#10
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H
DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
END
MOV R3,#F7H ; 扫描初始值
MOV R1,#00H ; 取码指标
SCAN1: MOV A,R3 ; 开始扫描
MOV P1,A ; 将扫描值输出到 P1
MOV A,P1 ; 读入 P1 判断是否有按下
MOV R4,A ; 存到 R4, 判断是否放开
SETB C ; C=1
MOV R5,#04H ; 扫描 P14~P17
L1: RLC A ; 将按键值左移一位元
JNC KEYIN ; 若 C=0, 有按, 执行 KEYIN
INC R1 ; 将指标值加 1, 继续扫描下一行
DJNZ R5,L1 &
nbsp; ; 扫描四行
MOV A,R3 ; 载入扫描值
SETB C ; C=1
RRC A ; 扫描下一列(P13~P10)
MOV R3,A ; 存回扫描值
JC SCAN1 ; C=1, 尚未完成扫描
RET ; 结束键盘扫描, 回到 Main Program
KEYIN: MOV R7,#10 ; 消除弹跳
D2: MOV R6,#248
DJNZ R6,$
DJNZ R7,D2
D3: MOV A,P1 ; 读入 P1
XRL A,R4
JZ D3
MOV A,R1
MOV DPTR,#TABLE
MOVC A,@A+DPTR
Table:
db 0c0h,0f9h,0a4h,0b0h,099h ;0-4
db 092h,082h,0f8h,080h,090h ;5-9
db 088h,083h,0a7h,0a1h,086h ;A-E
db 08eh ;F
end
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |