第3套题矩阵键盘扫描分析
简述扫描法识别矩阵式键盘上闭合键的方法

简述扫描法识别矩阵式键盘上闭合键的方法扫描法是一种常见的识别矩阵式键盘上闭合键的方法。
矩阵式键盘是指将键排列成矩阵形式的键盘,其中每个键都有一个唯一的行列坐标。
扫描法通过依次扫描矩阵中的每个键,并检测按下的键是否闭合来实现键盘输入的识别。
以下是利用扫描法识别矩阵式键盘上闭合键的一般步骤:1.确定矩阵的行数和列数:首先确定键盘的行数和列数,通常可以通过读取键盘的配置文件或者手动测量来获取。
2.设置输入输出引脚:将矩阵的行和列分别与输入输出引脚相连,通常使用数字输入输出引脚来实现。
根据具体的硬件平台和编程语言,设置引脚可以使用GPIO库或者其他相关库函数。
3. 循环扫描键盘:使用一个循环结构不断扫描键盘的状态。
一般的循环结构可以使用while或者for语句实现。
4.逐行扫描:在每次循环中,按照从上到下的顺序逐行扫描键盘。
可以使用一个循环结构来实现逐行扫描。
5.逐列检测:对于每行键盘键,按照从左到右的顺序逐列检测。
通过将当前的行输入高电平,然后逐一检测列的输入状态,以确定是否有键闭合。
如果检测到闭合键,可以记录下当前的行列坐标。
6.处理按键操作:在检测到闭合键后,根据该键的行列坐标来进行相应的键盘输入处理。
可以通过根据行列坐标查找键对应的ASCII码或者其他键值来实现。
7.更新循环:在完成当前一次循环后,更新循环计数器,继续循环扫描键盘。
需要注意的是,扫描法是一种实时性较强的识别方法,需要以较高的频率(例如每秒数十次)循环扫描键盘,以确保能够准确地检测到闭合键。
此外,具体的实现方法可能会因硬件平台和编程语言的不同而有所差异,需要根据具体的情况进行调整。
总结起来,扫描法通过按照一定的顺序逐行逐列扫描矩阵式键盘,并根据检测到的闭合键的行列坐标来进行识别,实现了键盘输入的功能。
这种方法简单、可靠,被广泛应用在许多电子设备和系统中。
矩阵键盘扫描

矩阵键盘扫描1.实验目的与效果:4¡4矩阵键盘在众多场合有举足轻重的地位,所以有必要学好矩阵键盘扫描的编程。
实验板上的矩阵键盘是接单片机P2口的,以P2.4-P2.7作输出线,P2.0-P2.3作输入线;每按一个键会在数码管上显示相关的信息。
键盘上可以这样来定义,这只是个例子,用户在运用矩阵键盘键值是可以重新定义之。
2.原理图:矩阵键盘连接图3.实验板上操作:1)矩阵键盘在实验板上已经固定连接P2口了。
2)将HEX文件烧到单片机上。
3)将数码管的位选拨码开关拨到ON上。
4.实物连接图:拨码开关全部拨到ON5. C语言程序://MCU:AT89S51//晶振:12M#include"AT89X51.H"unsigned char code numcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0X88,0X83,0XC6,0XA1,0X86,0X8E,0XFF};//数字0~9及ABCDEF共阳数码管代码unsigned char code charcode[]={0xc0,0xc7,0xc7,0x86,0x89};// HELLO 字样共阳数码管代码unsigned char code bitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管位选代码unsigned char dispbuf[8]={16,16,16,0,1,2,3,4};unsigned char disp_bit_count;unsigned char disp_count;unsigned char temp;unsigned char key;unsigned char i,j;/********1ms延时子程序***********/delay_nms(unsigned int n){unsigned int i;unsigned char j;for(i=0;i<n;i++)for(j=0;j<120;j++); //空操作}unsigned char keyscan(void){P2=0xff;P2_4=0;temp=P2;temp=temp&0x0f;if (temp!=0x0f){delay_nms(10);temp=P2;temp=temp&0x0f;if (temp!=0x0f){temp=P2;temp=temp&0x0f;switch(temp){case 0x0e:key=7;break;case 0x0d:key=8;break;case 0x0b:key=9;break;case 0x07:key=10;break;}temp=P2;temp=temp & 0x0f;while(temp!=0x0f){temp=P2;temp=temp&0x0f;}}}P2=0xff;P2_5=0;temp=P2;temp=temp&0x0f;if (temp!=0x0f){delay_nms(10);temp=P2;temp=temp&0x0f;if (temp!=0x0f){temp=P2;temp=temp&0x0f;switch(temp){case 0x0e:key=4;break;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=11;break;}temp=P2;temp=temp & 0x0f;while(temp!=0x0f){temp=P2;temp=temp&0x0f;}}}P2=0xff;P2_6=0;temp=P2;temp=temp&0x0f;if (temp!=0x0f){delay_nms(10);temp=P2;temp=temp&0x0f;if(temp!=0x0f){temp=P2;temp=temp&0x0f;switch(temp){case 0x0e:key=1;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07:key=12;break;}temp=P2;temp=temp&0x0f;while(temp!=0x0f){temp=P2;temp=temp&0x0f;}}}P2=0xff;P2_7=0;temp=P2;temp=temp & 0x0f;if (temp!=0x0f){delay_nms(10);temp=P2;temp=temp&0x0f;if (temp!=0x0f){temp=P2;temp=temp & 0x0f;switch(temp){case 0x0e:key=0;break;case 0x0d:key=13;break;case 0x0b:key=14;case 0x07:key=15;break;}temp=P2;temp=temp & 0x0f;while(temp!=0x0f){temp=P2;temp=temp & 0x0f;}}}return (key);}void main(void){TMOD=0x02; //使用定时器0,选择方式2(常数自动重装的8位定时器)TH0=0x06; //保存数值,用于自动重装TL0=0x06; //定时250uS初值TR0=1; //开定时器0ET0=1; //开定时器0溢出中断EA=1; //开总中断while(1){dispbuf[0]=keyscan();}}/**********T0250uS中断服务程序***************/void t0(void) interrupt 1 using 0{disp_count++;if(disp_count==8){disp_count=0;if(disp_bit_count>=3)P0=charcode[dispbuf[disp_bit_count]];elseP0=numcode[dispbuf[disp_bit_count]];P1=bitcode[disp_bit_count];disp_count=0;disp_bit_count++;if(disp_bit_count==8){disp_bit_count=0;}}}。
行列式键盘扫描

实验二 行列式键盘扫描一. 实验内容与目的1. 实验内容利用行列式键盘,当按下键盘中的一个键子时会在数码管上显示出相应的键值,要求键盘有去抖功能,数码管显示的键值能进行移位。
2,实验目的学会行列式键盘扫描的原理与方法,进一步强化对MSP430I/O 口使用方法的掌握,加强msp430C 语言编程的能力。
二. 方法与结果键盘扫描:利用P3口进行键盘扫描,如图,令P3.0~P3.3为输出端口,P3.4~P3.7为输入端口,由于P3.4~P3,7接了上拉电阻,所以当没有键子按下时P3.4~P3.7都为‘1’,当有键子按下时P3.4~P3.7就有可能发生变化。
所以键盘扫描式先让P3.0~P3.3都为‘0’,当有键子按下时P3.4~P3.7就会有一个由‘1’变为‘0’,根据哪一个变为‘0’就能判断出相应的列有键子按下,再让P3.0~p3.3逐个变为‘1’判断出哪一行有键子按下进而确定出哪一个键子按下。
11221112221122311224112251122611227112281122911221122#1122*1122A 1122B1122C1122DR2510k R2610kR2710kR2810kP_30P_31P_32P_33P_34P_35P_36P_37P3.0~p3.3为‘0’P3.4~p3.7都为‘1’P3.4~P3.7不都为‘1’ 令P3.0~p3.3逐个为‘1’ 确定列确定行当P3.4~p3.7都为‘1’确定键值数码管显示:数码管位选与段选共用P1.0~P1.3,利用锁存器74HC373分时进行段选和位选,P6.1和P6.2控制74HC373,从而使相应数码管显示相应数。
电路图如下:e 1d 2d p3c 4g 546b 73829f 10a 11112seg4O E 1Q 02D 03D 14Q 15Q 26D 27D 38Q 39G N D 10L E11Q 412D 413D 514Q 515Q 616D 617D 718Q 719V C C 2074HC373_174HC373O E 1Q 02D 03D 14Q 15Q 26D 27D 38Q 39G N D 10L E11Q 412D 413D 514Q 515Q 616D 617D 718Q 719V C C 2074HC373_274HC373R19100R20100R21100R22100R2310k R2410k P_61P_62VCCVCCGND GNDGND GND GNDGNDP_10P_11P_12P_13P_14P_15P_16P_17三. 实验程序#include<msp430.h> void KEYSCAN(); void TUBESCAN();void KEYSLOVE( unsigned int key); unsigned char const table[]={0xff,0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0~F 码值 unsigned int s1=0,s2=0,s3=0,s4=0; //s1~s4保存相应键值,进行显示 unsigned int key;void delay1(unsigned int i) {while(i--); }void main() {WDTCTL=WDTPW+WDTHOLD; P1DIR=0xff; P1SEL=0x00; P3SEL=0x00; P3DIR=0x0f;P6DIR=BIT1+BIT2; TUBESCAN(); P3OUT=0xf0; while(1)KEYSCAN();TUBESCAN();}}void KEYSCAN(){P3OUT=0xf0;if(P3IN!=0xf0){switch(P3IN){case (0xe0):P3OUT=0x01;if(P3IN==0xf1) {key=16;break;}P3OUT=0x02;if(P3IN==0xf2) {key=12;break;}P3OUT=0x04;if(P3IN==0xf4) {key=8;break;}P3OUT=0x08;if(P3IN==0xf8) {key=4;break;}case (0xd0):P3OUT=0x01;if(P3IN==0xf1) {key=15;break;}P3OUT=0x02;if(P3IN==0xf2) {key=11;break;}P3OUT=0x04;if(P3IN==0xf4) {key=7;break;}P3OUT=0x08;if(P3IN==0xf8) {key=3;break;}case (0xb0):P3OUT=0x01;if(P3IN==0xf1) {key=14;break;}P3OUT=0x02;if(P3IN==0xf2) {key=10;break;}P3OUT=0x04;if(P3IN==0xf4) {key=6;break;}P3OUT=0x08;if(P3IN==0xf8) {key=2;break;}case (0x70):P3OUT=0x01;if(P3IN==0xf1) {key=13;break;}P3OUT=0x02;if(P3IN==0xf2) {key=9;break;}P3OUT=0x04;if(P3IN==0xf4) {key=5;break;}P3OUT=0x08;if(P3IN==0xf8) {key=1;break;}}P3OUT=0xf0;KEYSLOVE(key);} //键盘扫描函数,得到相应的键值key }void KEYSLOVE( unsigned int key){delay1(200);if(P3IN!=0xf0){while(P3IN!=0xf0) TUBESCAN(); //键盘去抖,保证当手松开时读取键值if(s4==0)s4=s3;s3=s2;s2=s1;s1=key;}else{if(key==16){s1=0;s2=0;s3=0;s4=0;key=0;}}}} //将得到的键值进行处理:移位/重置void TUBESCAN(){P6OUT=0x02;P1OUT=table[s4];P6OUT=0x04;P1OUT=0x01;delay1(400);P6OUT=0x02;P1OUT=table[s3];P6OUT=0x04;P1OUT=0x02;delay1(400);P6OUT=0x02;P1OUT=table[s2];P6OUT=0x04;P1OUT=0x04;delay1(400);P6OUT=0x02;P1OUT=table[s1];P6OUT=0x04;P1OUT=0x08;delay1(400);} //数码管扫描,使数码管保持四.行列式键盘实验总结①做行列是键盘重点是键盘扫描确定键值,键盘扫描也有多种方式,要多思考确定最优方式,采用本实验中的键盘扫描方式当没有键子按下时不必执行键盘扫描的其他程序,将更多的时间给了数码管扫描,挺优的,在着手写程序之前一定要筹划如何去写,要寻求简单易行的方法,写程序规划挺重要的。
单片机矩阵键盘扫描的两种方式

单片机矩阵键盘扫描的两种方式单片机矩阵键盘扫描的两种方式矩阵键盘扫描方式:第一种:逐行扫描法,就是一行一行的扫描。
实现代码如下(键盘连接P2口):#define NO_KEY 0XFF#define KEY_LO() P2 &= 0XF0#define KEY_HI() P2 |= 0X0F#define KEY_L(i) P2 &= ~(1<<i)#define KEY_RD() ((P2>>4) & 0x0f)UINT8 OnceKey(void){UINT8 line = 0;UINT8 key = NO_KEY;//key valueKEY_LO();if (KEY_RD() == 0X0F){KEY_HI();return NO_KEY;}for (line=0; line<4; line ++){KEY_HI();KEY_L(line);key = KEY_RD();switch (key){case ROW_FIRST:key = 4*line + 0;break;case ROW_SECOND:key = 4*line + 1;break;case ROW_THIRD:key = 4*line + 2;break;case ROW_FOURTH:key = 4*line +3;break;default :key = 0x0f;break;}if (key < 0x10){return key;}}return NO_KEY;}第二种,线性反转法。
就是行和列分别读出。
实现代码如下:#define CVT(i) ((i)==(~1)&0x0f)? 0: ((i)==(~2)&0x0f)? 1: ((i)==(~4)&0x0f)? 2: ((i)==(~8)&0x0f)? 3: 4;#define KEY0_3HI() P2 |= 0X0F#define KEY0_3LO() P2 &= 0XF0#define KEY4_7HI() P2 |= 0XF0#define KEY4_7LO() P2 &= 0X0F#define KEY0_3RD() (P2 & 0X0F)#define KEY4_7RF() ((P2>>4) & 0X0F)UINT8 OnceKey(void){UINT8 line = NO_KEY;UINT8 row = NO_KEY;UINT8 key;KEY0_3HI();KEY4_7LO();line = KEY0_3RD();//读入行的值if (0x0f == line){key = NO_KEY;}else{KEY0_3LO();KEY4_7HI();row = KEY4_7RD();//读入列的值if (0x0f == row){key = NO_KEY;}else{key = CVT(line)*4 + CVT(row);}}KEY0_3HI();KEY4_7HI();return key; }。
矩阵键盘扫描及LED数码显示综合实验

实验三:矩阵键盘扫描及LED数码显示综合实验
一、实验要求
利用4×4键盘和一个LED数码管构成简单的输入显示系统,实现键盘输入和LED数码显示相应键值的功能。
二、实验目的
1.掌握数码管显示原理,及无译码显示电路的显示程序的编写;
1.理解矩阵键盘扫描的原理;
2.掌握矩阵键盘与51单片机接口的编程方法。
三、实验电路图
四、主要知识点
键盘扫描原理、无译码电路的显示原理。
五、实验流程图
六、实验效果:点击相应按键显示相应的键值
七、实验步骤
1.在keil环境下编写程序,汇编后生成*.Hex文件。
2.硬件验证
1)用ISP下载*.HEX程序到CPU
2)按连接表连接电路
3)检查验证结果。
八、连线表
十、源程序:自己编写源程序。
键盘扫描

case 0xef: managekey4();break;
case 0xdf: managekey5();break;
case 0xbf: managekey6();break;
* P1.0-P1.3为列线,P1.4-P1.7为行线 *
* 喇叭接P3.7口 矩阵键盘P1口, 数码管数据P0口,数码管控制P2口 *
* *
}
//--------------------------------------------------
main()
{
P0=0xFF; //置P0口
P2=0xFF; //置P2口
dis_buf=0xBF;
while(1)
temp=temp&0x0F;
temp=~(temp|0xF0);
if(temp==1)
key=0;
else if(temp==2)
key=1;
else if(temp==4)
key=2;
else if(temp==8)
else
{ for(a=0;a<4;a++)
P1=0xF0;
if(P1!=0xF0)
{
keyscan();
beep();
// while(P1!=0xF0); //等待键释放
}
}
//--------------------------------------------------
void beep()
}
//--------------------------------------------------
矩阵键盘原理

db 08eh ;F
end
D3:
MOV A,P1 ; 读入 P1
XRL A,R4
JZ D3
MOV A,R1
MOV DPTR,#TABLE
MOVC A,@A+DPTR
Table:
db0c0h,0f9h,0a4h,0b0h,099h ;0-4
db 092h,082h,0f8h,080h,090h ;5-9
RLC A ; 将按键值左移一位元
JNC KEYIN ; 若 C=0, 有按, 执行 KEYIN
INC R1 ; 将指标值加 1, 继续扫描下一行
DJNZ R5,L1 ; 扫描四行
MOV A,R3 ; 载入扫描值
SETB C ; C=1
RRC A ; 扫描下一列(P13~P10)
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:
MOV R3,A ; 存回扫描值
JC SCAN1 ; C=1, 尚未完成扫描
RET ; 结束键盘扫描, 回到 Main Program
YIN:
MOV R7,#10 ; 消除弹跳
D2:
MOV R6,#248
DJNZ R6,$
DJNZ R7,D2
由於这种按键是机械式的开关,当按键被按下时,键会震动一小段时间才稳定,為了避免让8051误判為多次输入同一按键,我们必须在侦测到有按键被按下,就Delay一小段时间,使键盘以达稳定状态,再去判读所按下的键,就可以让键盘的输入稳定。
矩阵键盘过程及扫描程序

键盘是单片机常用输入设备,在按键数量较多时,为了节省I/O口等单片机资源,一般采取扫描的方式来识别到底是哪一个键被按下。
即通过确定被按下的键处在哪一行哪一列来确定该键的位置,获取键值以启动相应的功能程序。
矩阵键盘的四列依次接到单片机的P1.0~P1.3,四行依次接到单片机的P1.4~P1.7;同时,将列线上拉,通过10K电阻接电源。
查找哪个按键被按下的方法为:一个一个地查找。
先第一行输出0,检查列线是否非全高;否则第二行输出0,检查列线是否非全高;否则第三行输出0,检查列线是否非全高;如果某行输出0时,查到列线非全高,则该行有按键按下;根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。
下面是具体程序:void Check_Key(void){unsigned char row,col,tmp1,tmp2;tmp1 = 0x10;//tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0for(row=0;row<4;row++) // 行检测{P1 = 0x0f; // 先将p1.4~P1.7置高P1 =~tmp1; // 使P1.4~p1.7中有一个为0tmp1*=2; // tmp1左移一位if ((P1 & 0x0f) < 0x0f)// 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测{tmp2 = 0x01; // tmp2用于检测出哪一列为0for(col =0;col<4;col++) // 列检测{if((P1 & tmp2)==0x00)// 该列如果为低电平则可以判定为该列{key_val =key_Map[ row*4 +col ];// 获取键值,识别按键;key_Map为按键的定义表return; // 退出循环}tmp2*=2; // tmp2左移一位}}}} //结束。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
分析一下题第三套综合题的键盘扫描问题,图如下(借用群里别人传的图)
//*KEYOUTPUT是键盘扫描时的输出地址,KEYINPUT是键盘读入时的地址
#define KEYOUTPUT (*(volatile INT8U *)0x56000044)
#define KEYINPUT (*(volatile INT8U *)0x56000044)
INT16U ScanKey()
{
INT16U key=0xFFFF; //注意key与i定义都是16位的数值
INT16U i;
INT8U temp=0xFF,output; //这里temp与output定义为8位的数值rGPECON= ((rGPECON &0xFFFFFF00) | 0x00000055); //初始化GPE0~GPE3为输出
rGPECON= rGPECON & 0xFFFF00FF;//初始化GPE4~GPE7为输入这里寄存器的初始化我就不多啰嗦了
for (i=1;(( i<= 8)&&(i>0));i<<=1 ) 下面是按行扫描,共四行,所以扫描4次(i从等于1开始,左移4次结果为8)。
注意第1次i的值为0x0001,化为二进制数是0000000000000001。
第2次,i左移1位(在二进制里左移),故值为0000000000000010,化为16进制数0x0002,第3次再左移1位,0x0004,第4次值为0x0008
{
output |= 0xFF; 这句是对output初始化
output &= (~i); 按行给低电平。
比如现在扫描到第二行,即 i为0x0002,取反后为0xFFFD,接下来output(0xFF)与~i相与,0xFF&0xFFFD值为0xFFFD(注意前面说到output定义为8位数值,它与16位数值相与后,只能保存8位数值),故最后output值为0xFD。
(将output的值由16进制化为2进制11111101。
根据上图如果对应到IO口就是GPE7-GPE0。
可以看到是给GPE1给了个低电平。
GPE1对应第2行)
KEYOUTPUT=output; 将output的值传给KEYOUTPUT
temp = KEYINPUT; 这句是读入输入的值
if ((temp&0xF0)!= 0xF0) temp读入的是GPE7-GPE0的值,可以看到如果有输入,那么GPE4-GPE7必然不会全为1。
做temp&0xF0是为了取出GPE7-GPE4的数据,后一个0xF0是用来判断列信号是否有0。
如果有则进入if语句。
{
key = (~i); 假设按下的键是6,它在第2行,则~i=0xFFFD,赋值后
key=0x0xFFFD。
key <<= 8; 将key值左移8位,即在16进制下是在末尾加2个零,为0x0xFFFD00,但key是16位数,故需要舍弃前两个FF,最终结果是key=0xFD00 key |= ((temp&0xF0)|0x0F); 刚说了按键6在第二行第3列,第3列对应GPE6为0,所以temp的值为1011****,(前面说了temp读入的是GPE7-GPE0的值,但此时GPE3-GPE0不需要过多考虑)即为0xB*。
与0xF0相与,再与0x0F 相或,结果为0xBF。
最后是key值与0xBF相或,的到最终结果0xFDBF
return (key); //函数返回按键对应的值
}
}
前面说了一大堆,可能有点啰嗦,这是为了给打算研究矩阵键盘的人看的,如果只是为了考试,可以看看下面简单的算法。
(仅限于此图,其他连接方法需要稍作修改)
比如按下的是‘确认’键,看一下行和列。
1行4列。
直接从if语句看
key = (~i); 第1行,给1取反是0xFFFE(怎么来的这在前面有,这个是基础)key <<= 8; 左移八位结果是0xFE00
key |= ((temp&0xF0)|0x0F) 将对应的列进行运算。
第4列对应GPE7=0,temp 值为0x7*,与0xF0相与,再和0x0F相或,值为0x7F。
0x7F再和key(0xFE00)相或,结果是0xFE7F。
晚上编辑的,部分解释语句难免有错误,如果大家有什么简洁易懂的解释方法可以在此基础上编辑,然后传到群里大家共享。
谢谢合作。