51单片机4×4矩阵按键扫描方法

合集下载

51键盘矩阵扫描程序

51键盘矩阵扫描程序

51键盘矩阵扫描程序假设按下的是S1键进行如下检测(4*4键盘)先在P3口输出p3 00001111低四位行会有变化cord_h =00001111&00001110 =00001110if !=00001111延时0.1uscord_h=00001110&00001111=00001110if !=00001111P3再输出11111110P3 =00001110|11110000=11111110输出高四位cord_l=P3&0xf0 //此时P3口就是(实际值)输入值01111110 而不是上面的11111110cord_l=01111110&11110000=01110000cord_h+cord_l=00001110+01110000=01111110=0x7e //此编码即为S1的编码#include <reg52.h>//包含头文件#define uchar unsigned char#define uint unsigned intunsigned char consttable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-Fuchar keyscan(void);void delay(uint i);void main(){uchar key;P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符while(1){key=keyscan();//调用键盘扫描,switch(key){case 0x7e:P0=table[0];break;//0 按下相应的键显示相对应的码值case 0x7d:P0=table[1];break;//1case 0x7b:P0=table[2];break;//2case 0x77:P0=table[3];break;//3case 0xbe:P0=table[4];break;//4case 0xbd:P0=table[5];break;//5case 0xbb:P0=table[6];break;//6case 0xb7:P0=table[7];break;//7case 0xde:P0=table[8];break;//8case 0xdd:P0=table[9];break;//9case 0xdb:P0=table[10];break;//acase 0xd7:P0=table[11];break;//bcase 0xee:P0=table[12];break;//ccase 0xed:P0=table[13];break;//dcase 0xeb:P0=table[14];break;//ecase 0xe7:P0=table[15];break;//f}}}uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法{uchar cord_h,cord_l;//行列值P3=0x0f; //行线输出全为0cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{delay(100); //去抖cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f){P3=cord_h|0xf0; //输出当前列线值cord_l=P3&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}void delay(uint i)//延时函数{while(i--);}。

4_4矩阵键盘扫描

4_4矩阵键盘扫描

//4*4矩阵式键盘扫描程序module keyscan(row, col, clk, key_buf);input [3:0] col; //列线定义input clk; //150MHZoutput [3:0] row; //行线定义output [7:0] key_buf; //键值输出口reg [3:0] row;reg [7:0] key_buf; //键值输出缓冲寄存器reg [7:0] key_buf1; //键值暂存器reg [3:0] count1;reg [14:0] count2;reg [3:0] state;reg [3:0] state_temp;reg sec, en;/*********************产生5MHZ方波****************/ always@(posedge clk )beginif(count1 == 4'd15)beginsec <= ~sec;count1 <= 4'd0;endelsecount1 <= count1+1'b1;endalways@(negedge sec)beginif(en)begincase(state)/******************** 准备进入行扫描状态*************/4'd0://KEY //开始扫描beginrow[3:0] <= 4'b0000; //行线全部置零state_temp = 4'd1;state = 4'd9; //5ms消抖end/*********************扫描第一行**********************/4'd1://KEYTEMPbeginif(col[3:0] == 4'b1111) //判断是否有键按下?state = 4'd0; //没有就重新扫描elsebeginrow[3:0] <= 4'b1110;state_temp = 4'd2;state = 4'd9; //如果有就延时去抖endend/********************检测第一行键值*******************/4'd2://ROW1begincase({row[3:0],col[3:0]}) //第一行判断8'b1110_1111: //无键按下beginkey_buf1 <= 8'b1111_1111;state = 4'd3; //进入第二行扫描end8'b1110_1110: //键值1beginkey_buf1 <= 8'b1111_1110; //键值放入key_buf1state = 4'd10; //等待弹起end8'b1110_1101: //键值2beginkey_buf1 <= 8'b1111_1101;state = 4'd10;end8'b1110_1011: //键值3beginkey_buf1 <= 8'b1111_1011;state = 4'd10;end8'b1110_0111: //键值4beginkey_buf1 <= 8'b1111_0111;state = 4'd10;enddefault:beginkey_buf1 <= 8'b1111_1111;state = 4'd3; //进入第二行扫描endendcaseend/*********************第二行扫描*********************/4'd3://ROW2TEMPbeginrow[3:0] <= 4'b1101;state_temp = 4'd4;state = 4'd9;end/***********************检测第二行键值***************/4'd4://ROW2begincase({row[3:0], col[3:0]})8'b1101_1111: //若无键按下beginkey_buf1 <= 8'b1111_1111;state = 4'd5; //进入第三行扫描end8'b1101_1110: //键值5beginkey_buf1 <= 8'b1110_1111;state = 4'd10; //等待弹起end8'b1101_1101: //键值6beginkey_buf1 <= 8'b1101_1111;state = 4'd10;end8'b1101_1011: //键值7beginkey_buf1 <= 8'b1011_1111;state = 4'd10;end8'b1101_0111: //键值8beginkey_buf1 <= 8'b0111_1111;state = 4'd10;enddefault:beginkey_buf1 <= 8'b1111_1111;state = 4'd5; //进入第三行扫描endendcaseend/**********************第三行扫描********************/4'd5://ROW3TEMPbeginrow[3:0] <= 4'b1011;state_temp = 4'd6;state = 4'd9;end/*********************检测第三行键值*****************/4'd6://ROW3begincase({row[3:0], col[3:0]})8'b1011_1111: //若无键按下beginkey_buf1 <= 8'b1111_1111;state = 4'd7; //进入第四行扫描end8'b1011_1110: //键值9beginkey_buf1 <= 8'b1111_1110;state = 4'd10; //等待弹起end8'b1011_1101: //键值10beginkey_buf1 <= 8'b1111_1100;state = 4'd10;end8'b1011_1011: //键值11beginkey_buf1 <= 8'b1111_1000;state = 4'd10;end8'b1011_0111: //键值12beginkey_buf1 <= 8'b1111_0000;state = 4'd10;enddefault:beginkey_buf1 <= 8'b1111_1111;state = 4'd7; //进入第四行扫描endendcaseend/********************第四行扫描**********************/4'd7://ROW4TEMPbeginrow[3:0] <= 4'b0111;state_temp = 4'd8;state = 4'd9;end/*********************检测第四行键值******************/ 4'd8://ROW4begincase({row[3:0], col[3:0]})8'b0111_1111: //若无键按下beginkey_buf1 <= 8'b1111_1111;state = 4'd0; //重新进入扫描end8'b0111_1110: //键值13beginkey_buf1 <= 8'b1110_0000;state = 4'd10; //等待弹起end8'b0111_1101: //键值14beginkey_buf1 <= 8'b1100_0000;state = 4'd10;end8'b0111_1011: //键值15beginkey_buf1 <= 8'b1000_0000;state = 4'd10;end8'b0111_0111: //键值16beginkey_buf1 <= 8'b0000_0000;state = 4'd10;enddefault:beginkey_buf1 <= 8'b1111_1111;state = 4'd0; //重新进入扫描endendcaseend/***********************去抖延时********************/ 4'd9://DELAYbeginif(count2 ==15'd25000)beginstate = state_temp;count2 <= 0;endelsecount2 <= count2+1'b1;end/************************等待弹起******************/ 4'd10://WAITbeginif(col[3:0] == 4'b1111)beginkey_buf <= key_buf1;state <= 4'd0;endelsestate = 4'd10;endendcaseend/*******************否则,变量初始化****************/ elsebeginstate = 4'd0;count2 <= 0;key_buf <= 8'b0000_0000;row[3:0] <= 4'b0000;en <= 1;endendendmodule附:程序配套的4*4矩阵键盘电路图其中:P2.3 ~P2.0对应row[3:0];P3.7 ~P3.4对应line[3:0]。

51单片机矩阵键盘行扫描

51单片机矩阵键盘行扫描

51单⽚机矩阵键盘⾏扫描————————————————————————————————————————————分类:按结构原理分:触点式开关按键⽆触点开关按键接⼊⽅式独⽴式按键矩阵式键盘————————————————————————————————————————————矩阵式键盘识别⽅法(⾏扫描法)检测列线的状态:列线Y4~Y7置⾼电平,⾏线Y0~Y3置低电平。

只要有⼀列的电平为低,则表⽰键盘该列有⼀个或多个按键被按下。

若所有列线全为⾼电平,则键盘中⽆按键按下。

判断闭合按键所在的位置:⾏线置⾼电平,列线置低电平。

检测⾏线的状态。

举例:当按下第⼀⾏第⼀列的按键时⾏扫描,⾏线为低电平,列线为⾼电平,得到 1110 0000列扫描,⾏线为⾼电平,列线为低电平,得到 0000 1110将得到的结果进⾏或运算,得到 1110 1110,对应第⼀⾏第⼀列,⼗六进制为0xEE按键表⾏列bin hex111110 11100xEE121101 11100xDE131011 11100xBE140111 11100x7E211110 11010xED221101 11010xDD231011 11010xBD240111 11010x7D311110 10110xEB321101 10110xDB331011 10110xBB340111 10110x7B411110 01110xE7421101 01110xD7431011 01110xB7440111 01110x77————————————————————————————————————————————矩阵式键盘应⽤实例实现结果:通过4*4矩阵键盘对应数码管显⽰0~F设计思路:当检测到按键被按下时,将此时⾏扫描的结果存⼊临时变量,再进⾏列扫描,得到的结果和临时变量进⾏或运算。

通过数组存放按键和数码管编码,⾏列扫描得到结果后遍历数组,找到对应的编码位置并显⽰数码管编码实现代码:1 #include <reg52.h>2 typedef unsigned char uchar;3 typedef unsigned int uint;4 uchar code KEY_TABLE[] =5 {60xEE, 0xDE, 0xBE, 0x7E,70xED, 0xDD, 0xBD, 0x7D,80xEB, 0xDB, 0xBB, 0x7B,90xE7, 0xD7, 0xB7, 0x7710 };11 uchar code TABLE[] =12 {130x3F, 0x06, 0x5B, 0x4F,140x66, 0x6D, 0x7D, 0x07,150x7F, 0x6F, 0x77, 0x7C,160x39, 0x5E, 0x79, 0x71,17 };18void Delay(uchar m)19 {20 --m;21 }22void main()23 {24 uchar temp, key, i;25while(1)26 {27 P3 = 0xF0;28if (P3 != 0xF0)29 {30 Delay(2000);31if (P3 != 0xF0)32 {33 temp = P3;34 P3 = 0x0F;35 key = temp | P3;36for (i = 0; i < 16; ++i)37if (key == KEY_TABLE[i])38break;39 P2 = TABLE[i];40 }41 }42 }43 }。

4×4矩阵键盘51单片机识别实验及程序

4×4矩阵键盘51单片机识别实验及程序

4×4矩阵键盘51单片机识别实验与程序1.实验任务如图4.14.2所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F〞序号。

对应的按键的序号排列如图4.14.1所示图4.14.12.硬件电路原理图图4.14.23.系统板上硬件连线〔1.把“单片机系统“区域中的P3.0-P3.7端口用8芯排线连接到“4*4行列式键盘〞区域中的C1-C4 R1-R4端口上;〔2.把“单片机系统〞区域中的P0.0/AD0-P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块〞区域中的任一个a-h端口上;要求:P0.0/AD0对应着a,P0.1/AD1对应着b,……,P0.7/AD7对应着h。

4.程序设计容〔1.4×4矩阵键盘识别处理(2.每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。

矩阵的行线和列线分别通过两并行接口和CPU通信。

每个按键的状态同样需变成数字量“0〞和“1〞,开关的一端〔列线〕通过电阻接VCC,而接地是通过程序输出数字“0〞实现的。

键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。

两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。

5.程序框图图4.14.3C语言源程序*include <AT89*51.H>unsigned char code table[]={0*3f,0*06,0*5b,0*4f,0*66,0*6d,0*7d,0*07,0*7f,0*6f,0*77,0*7c,0*39,0*5e,0*79,0*71};unsigned char temp;unsigned char key;unsigned char i,j;void main(void) {while(1){P3=0*ff;P3_4=0;temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {temp=P3;temp=temp & 0*0f; switch(temp){case 0*0e:key=7;break;case 0*0d:key=8;break;case 0*0b:key=9;break;case 0*07:key=10;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp & 0*0f; while(temp!=0*0f) {temp=P3;temp=temp & 0*0f; }}}P3=0*ff;P3_5=0;temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {temp=P3;temp=temp & 0*0f; switch(temp){case 0*0e:key=4;break;case 0*0d:break;case 0*0b:key=6;break;case 0*07:key=11;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp & 0*0f; while(temp!=0*0f) {temp=P3;temp=temp & 0*0f; }}}P3=0*ff;temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {temp=P3;temp=temp & 0*0f; switch(temp){case 0*0e:key=1;break;case 0*0d:key=2;break;case 0*0b:break;case 0*07:key=12;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp & 0*0f; while(temp!=0*0f) {temp=P3;temp=temp & 0*0f; }}}P3=0*ff;P3_7=0;temp=P3;temp=temp & 0*0f;if (temp!=0*0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp & 0*0f; if (temp!=0*0f) {temp=P3;temp=temp & 0*0f; switch(temp){case 0*0e:key=0;break;case 0*0d:key=13;break;case 0*0b:key=14;break;case 0*07:key=15;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp & 0*0f; while(temp!=0*0f) {temp=P3;temp=temp & 0*0f; }}}}}。

矩阵键盘扫描汇编程序

矩阵键盘扫描汇编程序

4*4矩阵键盘扫描汇编程序(基于51单片机)// 程序名称:4-4keyscan.asm;// 程序用途:4*4矩阵键盘扫描检测;// 功能描述:扫描键盘,确定按键值。

程序不支持双键同时按下,;// 如果发生双键同时按下时,程序将只识别其中先扫描的按键;// 程序入口:void;// 程序出口:KEYNAME,包含按键信息、按键有效信息、当前按键状态;//================================================================== ====PROC KEYCHKKEYNAME DATA 40H ;按键名称存储单元;(b7-b5纪录按键状态,b4位为有效位,;b3-b0纪录按键)KEYRTIME DATA 43H ;重复按键时间间隔SIGNAL DATA 50H ;提示信号时间存储单元KEY EQU P3 ;键盘接口(必须完整I/O口) KEYPL EQU P0.6 ;指示灯接口RTIME EQU 30 ;重复按键输入等待时间KEYCHK:;//=============按键检测程序========================================= ====MOV KEY,#0FH ;送扫描信号MOV A,KEY ;读按键状态CJNE A,#0FH,NEXT1 ;ACC<=0FH; CLR C ;Acc等于0FH,则CY为0,无须置0NEXT1:; SETB C ;Acc不等于0FH,则ACC必小于0 FH,;CY为1,无须置1MOV A,KEYNAMEANL KEYNAME,#1FH ;按键名称屏蔽高三位RRC A ;ACC带CY右移一位,纪录当前按键状态ANL A,#0E0H ;屏蔽低五位ORL KEYNAME,A ;保留按键状态;//=============判别按键状态,决定是否执行按键扫描=================== =====CJNE A,#0C0H,NEXT2 ;110按键稳定闭合,调用按键检测子程序SJMP KEYSCANNEXT2:CJNE A,#0E0H,NEXT3 ;111按键长闭合,重复输入允许判断SJMP WAITNEXT3:CJNE A,#0A0H,EXIT ;101干扰,当111长闭合处理ORL KEYNAME,#0E0HWAIT:MOV A,KEYRTIMEJNZ EXIT ;时间没到,退出;//=============键盘扫描程序========================================= =====KEYSCAN:MOV R1,#0 ;初始化列地址MOV R3,#11110111B ;初始化扫描码LOOP:MOV A,R3RL AMOV R3,A ;保留扫描码MOV KEY,A ;送扫描码MOV A,KEY ;读键盘ORL A,#0F0H ;屏蔽高四位CJNE A,#0FFH,NEXT31 ;A不等于FFH,说明该列有按键动作INC R1 ;列地址加1,准备扫描下一列CJNE R1,#4,LOOP ;列地址不等于4,扫描下一列SJMP EXIT ;没有按键,退出;//=============按键判断对应位等于零,说明该行有按键按下============= =====NEXT31:JB ACC.0,NEXT32MOV R2,#0 ;第0行有按键SJMP NEXT5NEXT32:JB ACC.1,NEXT33MOV R2,#1 ;第1行有按键SJMP NEXT5NEXT33:JB ACC.2,NEXT34MOV R2,#2 ;第2行有按键SJMP NEXT5NEXT34:MOV R2,#3 ;第3行有按键NEXT5: ;计算按键地址MOV A,R1RL ARL A ;列地址乘4(每列对应4行)ADD A,R2 ;加行地址MOV DPTR,#KEYTABMOVC A,@A+DPTRANL KEYNAME,#0E0HORL KEYNAME,A ;送按键(送值的时候已经置按键有效)MOV KEYRTIME,#RTIME ;送重复按键等待时间CLR KEYPL ;打开指示灯MOV SIGNAL,#10 ;送信号提示时间(每次按键闪10 0ms)EXIT:MOV KEY,#0FFH ;置键盘接口高电平RET ;退出;//=============按键名称表=========================================== =====KEYTAB:DB 1AH ;扫描码0,对应A ************************************ ******DB 1BH ;扫描码1,对应B ** **DB 1CH ;扫描码2,对应C ** I/O口 PX.4 PX.5 PX.6 PX.7 **DB 1DH ;扫描码3,对应D ** **DB 11H ;扫描码4,对应1 ** PX.0 A(0) 1(4) 2(8) 3 (C) **DB 14H ;扫描码5,对应4 ** **DB 17H ;扫描码6,对应7 ** PX.1 B(1) 4(5) 5(9) 6 (D) **DB 1EH ;扫描码7,对应E ** **DB 12H ;扫描码8,对应2 ** PX.2 C(2) 7(6) 8(A) 9 (E) **DB 15H ;扫描码9,对应5 ** **DB 18H ;扫描码A,对应8 ** PX.3 D(3) E(7) 0(B) F(F) **DB 10H ;扫描码B,对应0 ** **DB 13H ;扫描码C,对应3 ************************************ ******DB 16H ;扫描码D,对应6DB 19H ;扫描码E,对应9DB 1FH ;扫描码F,对应FEND第二种解法ORG 0000HSTART: MOV R0,#00H ;初始化程序,开始的延时是为了使硬件能够准备好DJNZ R0,$LOOP: MOV SP,#60HCALL KEYDISPLAY:MOV A,R4MOV DPTR,#TABLE ;定义字形表的起始地址MOVC A,@A+DPTR ;TABLE为表的起始地址MOV P2,ASJMP LOOP;子程序内容,P1口的低四位为行线,高四位为列线KEY: PUSH PSWPUSH ACCMOV P1,#0F0H ;令所有的行为低电平,全扫描字-P1.0-P1.3,列为输入方式;这一段只是验证有键按下,并不能判断是哪一行MOV R7,#0FFH ;设置计数常数,作为延时KEY1: DJNZ R7, KEY1MOV A,P1 ;读取P1口的列值ANL A,#0F0H ;判别有键值按下吗(当有键按下时,P1口的高四位就不全为1了,底四位还是都为0的);这个地方进行相或的原因,是因为要把底四位的0000变成1111,以便下一步进行求反ORL A,#0FH //这个地方原版上没有,这是又加了,如果不加的的话,是不对的********CPL A ;求反后,有高电平就有键按下JZ EKEY;累加器为0则转移(意为求反后本来全为0的,如果有键按下时,求反后高四位就有1了),退出LCALL DEL20ms ;有键按下,进行处理;下面进行行行扫描,1行1行扫SKEY: MOV A,#00HMOV R0,A ;R0作为行计数器,开始初值为0MOV R1,A ;R1作为列计数器,开始初值为0MOV R2,#0FEH ;R2作为扫描暂存字,开始初值为1111 1110,(第四位作为行扫描字)SKEY2: MOV A,R2MOV P1,A ;输出行扫描字,1111 1110NOPNOPNOP ;3个NOP操作使P1口输出稳定MOV A,P1 ;读列值(和开始一样)MOV R1,A ;暂存列值(第一次为**** 1110,既高四位有一位"可能"会为0)ANL A,#0F0H ;取高四位,ORL A,#0FH ;使第四位全部置1CPL ABIAOZHI:JNZ SKEY3 ;累加器为非0则转移指令(意思是判断到按键在这一行),转去处理INC R0 ;如果按键没在这一行,行计数器加1SETB C ;进位标志位加1,为了在左移的时候开始的低位0不在出现在低(循环一圈后)MOV A,R2RLC A ;带进位左移1位(形成下一行扫描字,再次扫描)MOV R2,AMOV A,R0;把加1后的行计数器R0和总共扫描次数(4次比较)CJNE A,#04H,SKEY2 ;(扫描完了么)书本上这个地方也有错误,书本上写的是:SKEY1AJMP EKEY ;如果没有的话,退出;有键按下后行扫描过后,此为确列行SKEY3: MOV A,R1 ;JNB ACC.4,SKEY5 ;直接寻址位为0咋转移指令JNB ACC.5,SKEY6JNB ACC.6,SKEY7JNB ACC.7,SKEY8AJMP EKEY //我自己感觉到这命令没有用处SKEY5: MOV A,#00H ;存0列号MOV R3,AAJMP DKEYSKEY6: MOV A,#01H ;存1列号MOV R3,AAJMP DKEYSKEY7: MOV A,#02H ;存2列号MOV R3,AAJMP DKEYSKEY8: MOV A,#03H ;存3列号MOV R3,AAJMP DKEY;取出具体的行号,再加上列号,最终确认按键的号码DKEY: //MOV R4,#00HMOV A,R0MOV B,#04HMUL AB ;让行号*4,第四位放在A中(总共就4行,相乘后一定<16,也就是只有第四位有值)ADD A,R3 ;让行号和列号相加,最终确认任按键的具体号MOV R4,AEKEY: POP ACCPOP PSWRET ;按键扫描处理函数DEL20ms:MOV R7,#2DL2: MOV R6,#18DL1: MOV R5,#255DJNZ R5,$DJNZ R6,DL1DJNZ R7,DL2RET;此为共阴极数码管的数字表TABLE: DB 3FH ;0DB 06H ;1DB 5BH ;2DB 4FH ;3DB 66H ;4DB 6DH ;5DB 7DH ;6DB 27H ;7DB 7FH ;8DB 6FH ;9DB 77HDB 7CHDB 39HDB 5EHDB 79HDB 71HEND第三种PIC单片机键盘扫描汇编程序;本程序用于PIC外接键盘的识别,通过汇编程序,使按下K1键时第一个数码管显示1,按下K2键时第一;个数码管上显示2,按下K3键时第一个数码管上显示3,按下K4键时第一个数码管上显示4,;汇编程序对键盘的扫描采用查询方式LIST P=18F458INCLUDE "P18F458.INC";所用的寄存器JIANR EQU 0X20FLAG EQU JIANR+1 ;标志寄存器DEYH EQU JIANR+2DEYL EQU JIANR+3F0 EQU 0 ;FLAG的第0位定义为F0ORG 0X00GOTO MAINORG 0X30;*************以下为键盘码值转换表****************** CONVERT ADDWF PCL,1RETLW 0XC0 ;0,显示段码与具体的硬件连接有关RETLW 0XF9 ;1RETLW 0XA4 ;2RETLW 0XB0 ;3RETLW 0X99 ;4RETLW 0X92 ;5RETLW 0X82 ;6RETLW 0XD8 ;7RETLW 0X80 ;8RETLW 0X90 ;9RETLW 0X88 ;ARETLW 0X83 ;BRETLW 0XC6 ;CRETLW 0XA1 ;DRETLW 0X86 ;ERETLW 0X8E ;FRETLW 0X7F ;"."RETLW 0XBF ;"-"RETLW 0X89 ;HRETLW 0XFF ;DARKRETURN;***************PIC键盘扫描汇编程序初始化子程序***************** INITIALBCF TRISA,5 ;置RA5为输出方式,以输出锁存信号BCF TRISB,1BCF TRISA,3BCF TRISE,0BCF TRISE,1BSF TRISB,4 ;设置与键盘有关的各口的输入输出方式BCF TRISC,5BCF TRISC,3 ;设置SCK与SDO为输出方式BCF INTCON,GIE ;关闭所有中断LW 0XC0WF SSPSTAT ;设置SSPSTAT寄存器LW 0X30WF SSPCON1 ;设置SPI的控制方式,允许SSP方式,并且时钟下降;沿发送数据,与"74HC595当其SCLK从低到高电平;跳变时,串行输入数据(DI)移入寄存器"的特点相对应LW 0X01WF JIANR ;显示值寄存器(复用为键值寄存器)赋初值CLRF FLAG ;清除标志寄存器RETURN ;返回;**************显示子程序*****************DISPLAYCLRF PORTAWF SSPBUFAGAINBTFSS PIR1,SSPIFGOTO AGAINNOPBCF PIR1,SSPIFBSF PORTA,5 ;详细的程序语句请参考 pic教程语句部分,可在首页搜索。

单片机矩阵键盘扫描的两种方式

单片机矩阵键盘扫描的两种方式

单片机矩阵键盘扫描的两种方式单片机矩阵键盘扫描的两种方式矩阵键盘扫描方式:第一种:逐行扫描法,就是一行一行的扫描。

实现代码如下(键盘连接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; }。

4X4按键扫描

4X4按键扫描

#include<reg52.h>#include<absacc.h>#include<stdio.h>#define uchar unsigned char#define unint unsigned int#define false 0#define true 1#define KEY_NULL 0xFF#define KEY_0 0#define KEY_1 1#define KEY_2 2#define KEY_3 3#define KEY_4 4#define KEY_5 5#define KEY_6 6#define KEY_7 7#define KEY_8 8#define KEY_9 9#define KEY_A 10#define KEY_B 11#define KEY_C 12#define KEY_D 13#define KEY_E 14#define KEY_F 15sbit P1_0 = P1^0;sbit P1_1 = P1^1;sbit P1_2 = P1^2;sbit P1_3 = P1^3;sbit P1_4 = P1^4;sbit P1_5 = P1^5;sbit P1_6 = P1^6;sbit P1_7 = P1^7;uchar code table[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};/***************************************************************** 函数名: ScanKeyPress功能描述: 行列键盘扫描返回值: temp*****************************************************************/ uchar ScanKeyPress(void){uchar temp;P1_0 = false;temp = KEY_NULL;if (!P1_4) temp = KEY_1;if (!P1_5) temp = KEY_2;if (!P1_6) temp = KEY_3;if (!P1_7) temp = KEY_4;P1_0 = true;P1_1 = false;if (!P1_4) temp = KEY_5;if (!P1_5) temp = KEY_6;if (!P1_6) temp = KEY_7;if (!P1_7) temp = KEY_8;P1_1 = true;P1_2 = false;if (!P1_4) temp = KEY_9;if (!P1_5) temp = KEY_0;if (!P1_6) temp = KEY_A;if (!P1_7) temp = KEY_B;P1_2 = true;P1_3 = false;if (!P1_4) temp = KEY_C;if (!P1_5) temp = KEY_D;if (!P1_6) temp = KEY_E;if (!P1_7) temp = KEY_F;P1_3 = true;return temp;}/***************************************************************** 函数名: delay功能描述: 延迟子程序返回值: 无*****************************************************************/ void delay(unint delay){unint i;for(;delay>0;delay--){for(i=0;i<18;i++){;}}}/***************************************************************** 函数名: display功能描述: 显示返回值: 无*****************************************************************/ void display(uchar K){P2=table[K];}void main(void){uchar key;while(1){key=ScanKeyPress(); /* 行列键盘扫描*/delay(10); /* 去抖*/display(key); /* 显示结果*/}}。

矩阵键盘扫描显示键值

矩阵键盘扫描显示键值

课程报告课程新型单片机实践题目4*4矩阵键盘扫描显示键值二级学院班级姓名学号指导教师设计时间2011.11.15~2011.12.14常州工学院《新型单片机》设计任务书学院:专业:自动化班级:绪论 (4)第一章总体方案设计 (5)第二章系统硬件电路的设计 (6)第三章系统软件电路的设计 (8)3.1软件设计思想 (8)3.2主程序设计 (9)3.3子程序设计 (9)3.3.1 动态显示程序设计 (10)3.3.2 按键程序设计 (11)第四章调试及性能分析 (14)4.1软件调试 (14)4.2性能分析 (15)总结 (16)参考文献 (16)附录 (17)A元件清单 (17)8、瓷片电容 (17)B总原理图 (18)C程序清单 (19)C实物图 (22)绪论制作一个检测4*4 矩阵键盘的按键编码的实验,把实际按键的键值的八位编码先转换成从0000—1111 的编码,再译成数码管能识别的八位编码,在数码管动态显示时,矩阵键盘的第一行对应00—03,4*4 第二行对应04—07,第三行08—11,第四行对应12—15。

原理:1.键盘的工作原理:.键盘的工作原理:按键设置在行、列线交点上,行、列线分别连接到按键开关的两端。

行线通过上拉电阻接到+5V 电源上。

无按键按下时,行线处于高电平的状态,而当有按键按下时,行线电平与此行线相连的列线电平决定。

2.行列扫描法原理:原理:.行列扫描法原理第一步,使行线为编程的输入线,列线是输出线,拉低所有的列线,判断行线的变化,如果有按键按下,按键按下的对应行线被拉低,否则所有的行线都为高电平。

第二步,在第一步判断有键按下后,延时10ms 消除机械抖动,再次读取行值,如果此行线还处于低电平状态则进入下一步,否则返回第一步重新判断。

第三步,开始扫描按键位置,采用逐行扫描,每间隔1ms 的时间,分别拉低第一列,第二列,第三列,第四列,无论拉低哪一列其他三列都为高电平,读取行值找到按键的位置,分别把行值和列值储存在寄存器里。

4×4键盘扫描程序

4×4键盘扫描程序

键盘程序假设P2.0-P2.3为H0-H3,P2.4-P2.7为L0-L3 (列) L0 L1 L2 L3(行) H0 0 1 2 3H1 4 5 6 7H2 8 9 A BH3 C D E F首先,行为P2口的低四位,而列为高四位。

P0口为数码管输出口。

第一种思路就是逐行逐列判断法。

#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar code table[17] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf};//八段数码管对应0-F值. uchar temp;void Delay_1ms(uint i)//1ms延时{uint x, j;for(j=0;j<i;j++)for(x=0;x<=148;x++);}void delay()//消除按键抖动延时{int i,j;for(i=0; i<=10; i++)for(j=0; j<=2; j++);}uchar Keyscan(void){uchar i,j,row,col;temp=P2&0xf0;for(i=0; i<4; i++){if(!(temp&(0x10<<i)))row=i;}P2=0x0f;temp=P2&0x0f;for(j=0; j<4; j++){if(!(temp&(0x01<<j)))col=j;}return (row+col*4);}void Main(void){uchar Key_Value=16; //读出的键值uchar i=0;while(1){P2 = 0xf0;temp=P2;if(temp != 0xf0){Delay_1ms(80); //按键消抖if(temp != 0xf0){Key_Value = Keyscan();}Delay_1ms(350); //按键消抖}P0 = table[Key_Value];//P0口输出数据到数码管}次读取结果组合起来就可以得到当前按键的特征编码。

4×4矩阵键盘识别技术

4×4矩阵键盘识别技术

实验课题:4×4矩阵键盘识别技术一实验目的1.熟悉和掌握AT89S51单片机相关的功能2.了解矩阵式键盘的内部结构,掌握至少一种常用的按键识别的方法3.利用AT89S51单片机和设计一个4×4矩阵键盘控制。

4.掌握子程序结构和子程序实际的基本知识。

二实验原理1. 4×4矩阵键盘的序列排列如图1-1,图1-12.如图1-2所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0―P1.3作输入线,以p1.4-P1.7作输出线,在数码管上显示每个按键的“0-F”序号.每个按键有它的行值和列值,行值和列值的组合就是识别这个按键的编码。

矩阵的行线和列线分别通过两并行接口和CPU通信。

每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。

键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。

两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。

3.程序框图三实验原理图四实验代码#include<AT89X51.H> unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsignedchartemp;unsignedcharkey;unsignedchari,j;voidmain(void){while(1){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f) {temp=P3;temp=temp&0x0f;switch(temp){case0x0e:key=7;break;case0x0d:key=8;break;case0x0b:key=9;break;case0x07:key=10;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3; temp=temp&0x0f; switch(temp){case0x0e:key=4;break;case0x0d:key=5;break;case0x0b:key=6;break;case0x07:key=11;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_6=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f; if(temp!=0x0f) {temp=P3;temp=temp&0x0f; switch(temp){ case0x0e:key=1;break;case0x0d:key=2;break;case0x0b:key=3;break;case0x07:key=12;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f; }}}P3=0xff;P3_7=0;temp=P3;temp=temp&0x0f; if(temp!=0x0f) {for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case0x0e:key=0;break; case0x0d:key=13;break;case0x0b:key=14;break;case0x07:key=15;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp&0x0f;while(temp!=0x0f){temp=P3;temp=temp&0x0f;}}}}}五实验小结1.通过本次试验熟练的掌握了AT89S51单片机相关的功能。

44矩阵式按键的接法

44矩阵式按键的接法

在单片机按键使用过程中,当键盘中按键数量较多时为了减少端口的占用通常将按键排列成矩阵形式如下图所示,在矩阵式键盘中每条水平线和垂直线在交叉处不直接连通而是通过一个按键加以连接,到底这样做是出意何种目的呢?大家看下面电路图,单片机的整一个8位端口可以构成 4*4=16 个矩阵式按键,相比独立式按键接法多出了一倍,而且线数越多区别就越明显,假如再多加一条线就可以构成 20个按键的键盘,但是独立式按键接法只能多出1个按键。

由此可见,在需要的按键数量比较多时,采用矩阵法来连接键盘是非常合理的,矩阵式结构的键盘显然比独立式键盘复杂一些,单片机对其进行识别也要复杂一些。

确定矩阵式键盘上任何一个键被按下通常采用行扫描法。

行扫描法又称为逐行查询法它是一种最常用的多按键识别方法。

因此,我们就以行扫描法为例介绍矩阵式键盘的工作原理。

图5-4(4*4矩阵式按键的接法)首先,不断循环地给低四位独立的低电平,然后判断键盘中有无键按下。

将低位中其中一列线(P1.0~P1.3中其中一列)置低电平然后检测行线的状态(高4位,即P1.4~P1.7,由于线与关系,只要与低电平列线接通,即跳变成低电平),只要有一行的电平为低就延时一段时间以消除抖动,然后再次判断,假如依然为低电平,则表示键盘中真的有键被按下而且闭合的键位于低电平的4个按键之中任其一,若所有行线均为高电平则表示键盘中无键按下。

再其次,判断闭合键所在的具体位置。

在确认有键按下后 ,即可进入确定具体闭合键的过程。

其方法是: 依次将列线置为低电平,即在置某一根列线为低电平时,其它列线为高电平。

同时再逐行检测各行线的电平状态;若某行为低,则该行线与置为低电平的列线交叉处的按键就是闭合的按键。

下面图5-5是4*4矩阵式按键接法的软件算法操作流程。

下面程序按照上述算法流程去编写的,其电路如图5-6,只是在图5-5的基础上多加了P0端口的8只LED灯。

从键盘中检测到一个键值,然后将这个值写到LED数码管上显示。

4x4矩阵键盘扫描原理

4x4矩阵键盘扫描原理

4x4矩阵键盘扫描原理
4x4矩阵键盘扫描原理是一种常用的键盘扫描方法,也称为矩阵键盘扫描。

它可以将多个按键连接在一起并使用较少的引脚来检测按键的状态。

4x4矩阵键盘由4行和4列组成,共有16个按键。

通常使用单片机或电路来进行扫描,以下是简要的原理:
1. 行扫描:首先,将行引脚设置为输出,同时将列引脚设置为输入,并将其上拉或下拉。

所有行引脚中只有一个为低电平,其余为高电平。

然后逐行检测按键状态。

2. 列检测:对于每一行,将对应的行引脚置为低电平后,检测列引脚的电平状态。

如果有按键按下,则相应的列引脚会变为低电平。

通过读取列引脚的状态,可以确定按键的位置。

3. 组合键:由于只能一次检测一行,因此当同时按下多个按键时,可能会导致误检。

为了解决这个问题,可以在检测到按键按下时,延迟一段时间,并再次检测按键的状态。

如果在第二次检测时仍然检测到按键按下,则确认按键有效。

4. 反向扫描:为了检测按键的释放状态,可以将行引脚设置为输入,列引脚设置为输出,并将其置为低电平。

然后逐列检测行引脚的电平状态,如果有按键释放,则相应的行引脚会变为高电平。

通过不断地循环扫描所有的行和列,可以实时检测按键的状态,并根据需要进行相应的处理。

51单片机4×4矩阵式键盘识别汇编程序

51单片机4×4矩阵式键盘识别汇编程序

;******************************************************;*标题: 51单片机4×4矩阵式键盘识别汇编程序;*******************************************************; 0 1 2 3 ---P20; 4 5 6 7 ---P21; 8 9 10 11 ---P22; 12 13 14 15 ---P23; | | | |; P24 P25 P26 P27;******************************************************************ORG 0000hAJMP MAINORG 0030hMAIN:MOV DPTR,#TAB ;将表头放入DPTRLCALL KEY;调用键盘扫描程序MOVC A,@A+DPTR ;查表后将键值送入ACCMOV P0,A;将Acc值送入P0口CLR P1.3 ;开显示LJMP MAIN ;返回调用子程序反复循环显示;----------------------------------------------------------------------KEY:LCALL KS ;调用检测按键子程序JNZ K1 ;有键按下继续LCALL DELAY2 ;无键按下调用延时去抖动程序AJMP KEY;返回继续检测有无按键按下K1:LCALL DELAY2LCALL DELAY2 ;有键按下继续延时去抖动LCALL KS ;再一次调用检测按键程序JNZ K2 ;确认有按下进行下一步AJMP KEY;无键按下返回继续检测K2:MOV R2,#0EFH ;将扫描值送入R2暂存MOV R4,#00H ;将第一列的列值00H送入R4暂存,R4用于存放列值。

K3:MOV P2,R2 ;将R2的值送入P1口L6:JB P2.0,L1 ;P1.0等于1跳转到L1MOV A,#00H ;将第一行的行值00H送入ACCAJMP LK ;跳转到键值处理程序JB P2.1,L2 ;P1.1等于1跳转到L2MOV A,#04H ;将第二行的行值送入ACCAJMP LK ;跳转到键值理程序进行键值处理L2:JB P2.2,L3 ;P1.2等于1跳转到L3MOV A,#08H ;将第三行的行值送入ACCAJMP LK ;跳转到键值处理程序L3:JB P2.3,NEXT ;P1.3等于1跳转到NEXT处MOV A,#0cH ;将第四行的行值送入ACCLK:ADD A,R4 ;行值与列值相加后的键值送入APUSH ACC ;将A中的值送入堆栈暂存K4:LCALL DELAY2 ;调用延时去抖动程序LCALL KS ;调用按键检测程序JNZ K4 ;按键没有松开继续返回检测POP ACC ;将堆栈的值送入ACCRETNEXT:INC R4 ;将列值加一MOV A,R2 ;将R2的值送入AJNB ACC.7,KEY;扫描完成跳至KEY处进行下一回合的扫描RL A;扫描未完成将A中的值右移一位进行下一列的扫描MOV R2,A;将ACC的值送入R2暂存AJMP K3 ;跳转到K3继续KS:MOV P2,#0FH ;将P1口高四位置0低四位值1MOV A,P2 ;读P1口XRL A,#0FH ;将A中的值与A中的值相异或RET ;子程序返回DELAY2: ;40ms延时去抖动子程序8*FA*2=40ms MOV R5,#08HL7:MOV R6,#0FAHL8:DJNZ R6,L8DJNZ R5,L7RETDB 0C0H;0DB 0F9H;1DB 0A4H;2DB 0B0H;3DB 099H;4DB 092H;5DB 082H;6DB 0F8H;7DB 080H;8DB 090H;9DB 088H;ADB 083H;bDB 0C6H;CDB 0A1H;dDB 086H;EDB 08EH;F END。

4x4矩阵键盘扫描例程

4x4矩阵键盘扫描例程

//4x4矩阵键盘扫描例程(C51)//使用P0口上的LED灯显示键盘扫描得到的键值//===============#include<reg51.h> //51系列单片机头文件#define uchar unsigned char#define uint unsigned int#define key_4x4_port P3 //定义4x4键盘使用的单片机端口uchar key; //存放扫描得到的键值void delayms(uint xms); //声明延时子程序void key_4x4_scan(); //声明4x4键盘扫描子程序,得到的键值送全局变量key //=====================void main(){P0=0xff; //P0开机初始化Key=0xff; //键盘值开机初始化为ff(检测到的键值应为0-15)while(1){key_4x4_scan(); //不停调用键盘扫描子程序P0=key; //用P0来显示键值}}//========================void delayms(uint xms) //延时子程序{ uint i, j;for (i=xms; i>0; i--)for (j-110; j>0; j--);}//======================void key_4x4_scan() //4x4键盘扫描子程序,得到的键值送全局变量key{ uchar temp;key_4x4_port=0xfe; //送出P3.0位0电平去扫描temp= key_4x4_port; //读出整个口得到的值temp=temp&0xf0; //屏蔽低4位if (temp!=0xf0) //假如高4位不全是1{ delayms(10); // 延时消抖再读temp=key_4x4_port;temp=temp&0xf0;if (temp!=0xf0) //消抖后如果再次高4位确定不是全1{ temp=key_4x4_port; //读出此次按键的值switch(temp){ case 0xee;key=0; break;case 0xde;key=1; break;case 0xbe;key=2; break;case 0x7e;key=3; break;}while(temp!=0xf0) //等待按键放开{ temp=key_4x4_port;temp=temp&0xf0;}}}//====次高位送0==========key_4x4_port=0xfd; //送出P3.1位0电平去扫描temp= key_4x4_port; //读出整个口得到的值temp=temp&0xf0; //屏蔽低4位if (temp!=0xf0) //假如高4位不全是1{ delayms(10); // 延时消抖再读temp=key_4x4_port;temp=temp&0xf0;if (temp!=0xf0) //消抖后如果再次高4位确定不是全1{ temp=key_4x4_port; //读出此次按键的值switch(temp){ case 0xed;key=4; break;case 0xdd;key=5; break;case 0xbd;key=6; break;case 0x7d;key=7; break;}while(temp!=0xf0) //等待按键放开{ temp=key_4x4_port;temp=temp&0xf0;}}}//====第3高位送0==========key_4x4_port=0xfb; //送出P3.2位0电平去扫描temp= key_4x4_port; //读出整个口得到的值temp=temp&0xf0; //屏蔽低4位if (temp!=0xf0) //假如高4位不全是1{ delayms(10); // 延时消抖再读temp=key_4x4_port;temp=temp&0xf0;if (temp!=0xf0) //消抖后如果再次高4位确定不是全1{ temp=key_4x4_port; //读出此次按键的值switch(temp){ case 0xeb;key=8; break;case 0xdb;key=9; break;case 0xbb;key=10; break;case 0x7b;key=11; break;}while(temp!=0xf0) //等待按键放开{ temp=key_4x4_port;temp=temp&0xf0;}}}//====第4高位送0==========key_4x4_port=0xf7; //送出P3.3位0电平去扫描temp= key_4x4_port; //读出整个口得到的值temp=temp&0xf0; //屏蔽低4位if (temp!=0xf0) //假如高4位不全是1{ delayms(10); // 延时消抖再读temp=key_4x4_port;temp=temp&0xf0;if (temp!=0xf0) //消抖后如果再次高4位确定不是全1{ temp=key_4x4_port; //读出此次按键的值switch(temp){ case 0xe7;key=12; break;case 0xd7;key=13; break;case 0xb7;key=14; break;case 0x77;key=15; break;}while(temp!=0xf0) //等待按键放开{ temp=key_4x4_port;temp=temp&0xf0;}}}}//==========End。

51单片机04矩阵按键逐行扫描,行列扫描代码

51单片机04矩阵按键逐行扫描,行列扫描代码

矩阵键盘扫描原理方法一:逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。

方法二:行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。

当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。

//行列扫描#include<reg51.h>#define GPIO_KEY P0#define GPIO_LCD P2unsigned char code a[17]={~0xfc,~0x60,~0xda,~0xf2,~0x66,~0xb6,~0xbe,~0xe0,~0xfe,~0xf6,~0xee,~0x3e,~0x9c,~0x7a,~0xde,~0x8e,~0x00}; //按位取反的用法void delay10ms();void keydown();//要与下面的定义一致void main(){GPIO_LCD=a[16];//初始化数码管while(1){keydown();}}void delay10ms(){unsigned char a,b;for(a=38;a>0;a--)for(b=130;b>0;b--);}void keydown()//检测按下,按下时需要消抖,检测松开,返回按键值//没有按键时保持{unsigned char n=0,key;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//读取按键是否按下{delay10ms(); //延时10ms消抖if(GPIO_KEY!=0x0f)//再次检测按键是否按下{GPIO_KEY=0x0f;//测试列switch(GPIO_KEY){case 0x07: key=0;break;case 0x0b: key=1;break;case 0x0d: key=2;break;case 0x0e: key=3;break;default : GPIO_LCD=a[16];}GPIO_KEY=0xf0;//测试行switch(GPIO_KEY){case 0x70: key=key;break;case 0xb0: key=key+4;break;case 0xd0: key=key+8;break;case 0xe0: key=key+12;break;default : GPIO_LCD=a[16];}GPIO_LCD=a[key];while(++n<5&&GPIO_KEY!=0xf0)//检测按键是否松开 {delay10ms();}}}}//逐行扫描#include<reg51.h>#define GPIO_KEY P0#define GPIO_LED P2unsigned char code a[17]={~0xfc,~0x60,~0xda,~0xf2,~0x66,~0xb6,~0xbe,~0xe0,~0xfe,~0xf6,~0xee,~0x3e,~0x9c,~0x7a,~0xde,~0x8e,~0x00}; //按位取反的用法void delay10ms();void keydown1();//要与下面的定义一致void main(){GPIO_LED=a[16];//初始化数码管while(1){keydown1();}}void keydown1(){unsigned char n=0,key;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//检测按键是否按下{delay10ms();//延时10ms消抖if(GPIO_KEY!=0x0f)//再次检测{GPIO_KEY=0x7f;//高四位轮流输出低电平 if(GPIO_KEY!=0x7f){switch(GPIO_KEY){case 0x77: key=0;goto AA;case 0x7b: key=1;goto AA;case 0x7d: key=2;goto AA;case 0x7e: key=3;goto AA;}}GPIO_KEY=0xbf;{switch(GPIO_KEY){case 0xb7: key=4;goto AA; case 0xbb: key=5;goto AA; case 0xbd: key=6;goto AA; case 0xbe: key=7;goto AA; }}GPIO_KEY=0xdf;if(GPIO_KEY!=0xdf){switch(GPIO_KEY){case 0xd7: key=8;goto AA; case 0xdb: key=9;goto AA; case 0xdd: key=10;goto AA; case 0xde: key=11;goto AA; }}GPIO_KEY=0xef;{switch(GPIO_KEY){case 0xe7: key=12;goto AA;case 0xeb: key=13;goto AA;case 0xed: key=14;goto AA;case 0xee: key=15;goto AA;}}GPIO_LED=a[16];goto BB;AA: GPIO_LED=a[key];BB: GPIO_KEY=0x0f;while(++n<5&&GPIO_KEY!=0x0f) delay10ms();//调用函数别忘记() }}}void delay10ms(){unsigned char a,b;for(a=38;a>0;a--)for(b=130;b>0;b--); }。

AT89C51单片机对4×4矩阵键盘进行动态扫描报告

AT89C51单片机对4×4矩阵键盘进行动态扫描报告

北京联合大学信息学院姓名:刘浩学号: 2010080403228 系别:电子工程系专业:电子信息工程同组人:徐笑、冯亚静、吴宾祝姗姗、孙迪指导教师:吴晶晶协助指导教师:训练任务:1、熟练掌握PROTEUS软件的使用;2、按照设计要求绘制电路原理图;3、能够按要求对所设计的电路进行仿真;基本要求及说明:1、按照设计要求自行定义电路图纸尺寸;2、设计任务如下:AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上;3、按照设计任务在Proteus 7Professional中绘制电路原理图;4、根据设计任务的要求编写程序,画出程序流程图,并在Proteus下进行仿真,实现相应功能。

目录1.任务说明................................................................... 错误!未定义书签。

2.原理图绘制说明 (1)3.流程图绘制以及说明 (2)4.PROTEUS仿真说明 (4)5.体会及合理化建议 (7)附录电路原理图 (8)参考文献 (9)一.任务说明AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上;按照设计任务在Proteus 7 Professional中绘制电路原理图;根据设计任务的要求编写程序,画出程序流程图,并在Proteus下进行仿真,实现相应功能。

二.原理图绘制说明1.原理图说明本实验是AT89C51单片机对4×4矩阵键盘进行动态扫描,当按键盘的键时,可将相应按键值(0~F)实时显示在数码管上。

4×4矩阵键盘是用4条I/O线作为行线,4条I/O线作为列线,在行线和列线的交叉点上设置一个按键,每个按键有它的行值和列值,用4条行线和列线分别接P1.0-P1.7,要进行数码管动态扫描,就要将数码管的七段a~f相应的与P0.0-P0.6相连接,即把输入端口P1.0-P1.7连接到4×4行列式按键上作为输入,P0.0-P0.6作为输出端口控制共阳级数码管a-g,对应的a-g 通过程序进行点亮或者熄灭来显示数值(0~F)。

4 4键盘扫描实验

4 4键盘扫描实验

4*4键盘扫描实验目的:1. 熟悉51系列单片机矩形4*4键盘扫描的工作原理。

2. 掌握4*4键盘扫描的编程方法。

实验原理:键盘实际上是由排列成矩阵形式的一系列按键开关组成的,它是单片机系统中最常用的人机联系的一种输入设备。

用户通过键盘可以向CPU输入数据、地址和命令。

键盘按其结构形式可分为编码式键盘和非编码式键盘两大类。

编码式键盘是由其内部硬件逻辑电路自动产生被按键的编码。

这种键盘使用方便,但价格较贵。

4×4表示有4根行线和4根列线,在每根行线和列线的交叉点上均分布1个单触点按键,共有16个按键。

行扫描法所谓行扫描法,就是通过行线发出低电平信号,如果该行线所连接的键没有按下的话,则列线所连接的输出端口得到的是全“1”信号;如果有键按下的话,则得到的是非全“1”信号。

列扫描法所谓列扫描法,就是通过列线发出低电平信号,如果该列线所连接的键没有按下的话,则列线所连接的输出端口得到的是全“1”信号;如果有键按下的话,则得到的是非全“1”信号。

实验内容:1.编写一程序,4*4键盘扫描#include"reg51.h"#define uchar unsigned char#define uint unsigned intuchar keyno;uchar disp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,0x39,0x5e,0x79,0x71}; uchar lieno;void delay1ms(uchar i){uchar j;while(i--)for(j=0;j<110;j++);}void main(){uchar tem;P0=0xff;while(1){P1=0x0f;if(P1!=0x0f)delay1ms(5);if(P1!=0x0f)tem=P1^0x0f;switch (tem){case 0x01:lieno=0;break;case 0x02:lieno=4;break;case 0x04:lieno=8;break;case 0x08:lieno=12;break;default :lieno=16;}P1=0xf0;tem=(P1>>4)^0x0f;switch (tem){case 0x01:keyno=lieno;break;case 0x02:keyno=lieno+1;break;case 0x04:keyno=lieno+2;break;case 0x08:keyno=lieno+3;}P0=disp[keyno];delay1ms(10);}}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
key=0xf0;//低四位为0
if(key==0xf0)//若无变化,证明按键松开
return 0;//返回0
else//否则,按键未松开
return 1;//返回1
}
//*********主函数*********//
int main()
{
key=0xff;//按键初始化
led=0xff;//关闭LED灯
//送至led显示
/*
eg:如果是第三行第二列按键按下
则第3个、第6(2列+4)个LED灯亮
如下图所示(Proteus仿真电路图)
*/
}
}
led_arry[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数组定义,便于显示
//******检测是否有按键按下*****//
uchar Check_Button()
{
key=0x0f;//高四位为0
if(key==0x0f)//若无变化,证明无按键按下
return 0;//返回0
else//否则
return 1;//返回1
}
//********行检测********//
uchar Line[]={0x0e,0x0d,0x0b,0x07}; //那个按键按下,检测出的状态则对应数组中的第几个数
void Check_Line()
{
uchar i;
key=0x0f;//高四位为0
/*****4×4按键扫描******/
/***编程要点
1.首先检测是否有按键按下
2.若有按键按下,即进行行检测,列检测
3.行检测:高4位设为0,低4位为1,进行检测0x0f
4.列检测:低4位设为0,高4位为1,进行检测0xf0
5.检测按键是否松开
6.送至LED显பைடு நூலகம்,前四个代表第几行
后四个代表第几列
for(i=0;i<4;i++)
{
if(key==Line[i])
{
line_num=i;//取出检测值
break;//结束行检测
}
}
}
//********列检测*********//
uchar Row[]={0xe0,0xd0,0xb0,0x70};//那个按键按下,检测出的状态则对应数组中的第几个数
while(1)
{
while(!Check_Button());//若无按键按下,则等待,若有继续下一步
Check_Line();//行检测
Check_Row();//列检测
while(Check_Release());//检测按键是否松开
led=led_arry[line_num]&led_arry[row_num+4];
P0为led灯口
P2为按键接口
****///
#include<reg51.h>
#define uchar unsigned char
#define key P2//P2口定义,便于调用
#define led P0//P0口定义,便于调用
unsigned char line_num,row_num;//行列定义
void Check_Row()
{
uchar j;
key=0xf0; //低4位置0
for(j=0;j<4;j++)
{
if(key==Row[j])
{
row_num=j;//取出检测值
break;//结束行检测
}
}
}
/*******按键松开检测*********/
uchar Check_Release()
相关文档
最新文档