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

合集下载

51单片机矩阵键盘代码

51单片机矩阵键盘代码

#include <reg51.h>#define uchar unsigned char#define uint unsigned intvoid dlms (void);uchar kbscan(void);/* 函数说明*/void main (void){uchar key;while (1){key=kbscan();/*调键扫描函数,返回键码送key保存*/dlms(); }}void dlms (void) /* 延时*/{uchar i;for (i=200;i>0;i--){}}uchar kbscan (void) /* 键盘扫描函数*/{uchar sccode, recode;P1=0xf0; /* P1.0~P1.3发全0,P1.4~P1.7输入*/ if((P1 & 0xf0)!=0xf0) /* 如P1口高四位不全为1有键按下*/{dlms ( );/* 延时去抖动*/if ((P1 & 0xf0)!=0xf0) /*再读输入值*/{sccode=0xfe /*最低位置为0*/while((sccode & 0x10)!=0) /*不到最后一行循环*/{P1=sccode;/*P1口输出扫描码*/If ((P1 & 0xf0)!=0xf0) /*如P1.4~P1.7不为全1,该行有键按下*/ {recode = P1 & 0xf0; / * 保留P1口高四位输入值(列码)*/ sccode= sccode& 0x0f; / * 保留扫描码低四位(行码)*/return (sccode+recode);/* 行码+列码=键编码返回主程序*/}elsesccode=(sccode <<1)| 0x01;/* 如该行无键按下,查下一行,行扫描值左移一位*/ }}}return(0);/* 无键按下,返回值为0 */}。

键盘扫描程序实验报告

键盘扫描程序实验报告

一、实验目的1. 理解键盘扫描的基本原理。

2. 掌握使用C语言进行键盘扫描程序设计。

3. 学习键盘矩阵扫描的编程方法。

4. 提高单片机应用系统的编程能力。

二、实验原理键盘扫描是指通过检测键盘矩阵的行列状态,判断按键是否被按下,并获取按键的值。

常见的键盘扫描方法有独立键盘扫描和矩阵键盘扫描。

独立键盘扫描是将每个按键连接到单片机的独立引脚上,通过读取引脚状态来判断按键是否被按下。

矩阵键盘扫描是将多个按键排列成矩阵形式,通过扫描行列线来判断按键是否被按下。

这种方法可以大大减少引脚数量,降低成本。

本实验采用矩阵键盘扫描方法,使用单片机的并行口进行行列扫描。

三、实验设备1. 单片机开发板(如51单片机开发板)2. 键盘(4x4矩阵键盘)3. 连接线4. 调试软件(如Keil)四、实验步骤1. 连接键盘和单片机:将键盘的行列线分别连接到单片机的并行口引脚上。

2. 编写键盘扫描程序:(1)初始化并行口:将并行口设置为输入模式。

(2)编写行列扫描函数:逐行扫描行列线,判断按键是否被按下。

(3)获取按键值:根据行列状态,确定按键值。

(4)主函数:调用行列扫描函数,读取按键值,并根据按键值执行相应的操作。

3. 调试程序:将程序下载到单片机,观察键盘扫描效果。

五、实验程序```c#include <reg51.h>#define ROW P2#define COL P3void delay(unsigned int ms) {unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 123; j++);}void scan_key() {unsigned char key_val = 0xFF;ROW = 0xFF; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值ROW = 0x00; // 初始化行delay(1); // 延时消抖key_val = ROW & COL; // 获取按键值}void main() {while (1) {scan_key();if (key_val != 0xFF) {// 执行按键对应的操作}}}```六、实验结果与分析1. 实验结果:程序下载到单片机后,按键按下时,单片机能够正确读取按键值。

51单片机矩阵键盘扫描程序

51单片机矩阵键盘扫描程序
void Timer0_isr(void) interrupt 1
{
TH0=(65536-2000)/256;//重新赋值2ms
TL0=(65536-2000)%256;
Display(0,8); //调用数码管扫描
}
/*------------------------------------------------
unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//显示段码值0~F
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
/*------------------------------------------------
uS延时函数,含有输入参数unsigned char t,无返回值
unsigned char是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5 uS

单片机矩阵键盘行列扫描程序学习资料

单片机矩阵键盘行列扫描程序学习资料
switch(key)
{
case 0x7e:P0=dofly[0];break;//0按下相应的键显示相对应的码值
case 0x7d:P0=dofly[1];break;//1
case 0x7b:P0=dofly[2];break;//2
case 0x77:P0=dofly[3];break;//3
case 0xbe:P0=dofly[4];break;//4
case 0xbd:P0=dofly[5];break;//5
case 0xbb:P0=dofly[6];break;//6
case 0xb7:P0=dofly[7];break;//7
case 0xde:P0=dofly[8];break;//8
if(cord_h!=0x0f) //先检测有无按键按下
{
delay(100); //去抖
if(cord_h!=0x0f)
{
cord_h=P3&0x0f; //读入列线值
P3=cord_h|0xf0; //输出当前列线值
cord_l=P3&0xf0; //读入行线值
return(cord_h+cord_l);//键盘最后组合码值
0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F
uchar keyscan(void);
void delay(uint i);
void main()
{
uchar key;
P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符
while(1)
{
key=keyscan();//调用键盘扫描,
//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍

矩阵键盘扫描汇编程序

矩阵键盘扫描汇编程序

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; }。

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

51单片机4×4矩阵按键扫描方法
{
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

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序

#include <reg51.h>#define KEY P1// ----------------------- 变量声明-------------------------------------------------------------------- void program_SCANkey(); // 程序扫描键盘 ,供主程序调用void delay(unsigned int N) ;// 延时子程序,实现 (16*N+24)us 的延时bitjudge_hitkey();// 判断是否有键按下,有返回 1,没 有返回 0void key_manage(unsigned char keycode); //键盘散转////函数名称:program_SCANkey//函数声明,变量定义unsigned char scan_key();表行,低四位代表列 )// 扫描键盘,返回键值 (高四位代void manage_key1(void);// 按键 1 处理程序 void manage_key2(void);// 按键 2 处理程序 void manage_key3(void);// 按键 3 处理程序 void manage_key4(void);// 按键 4 处理程序 //每个按键对应一个处理程序,这里// 函数功能:程序扫描键盘,// 有键按下完成按键处理,无键按下直接返回// -------------------------------------------------------------------------------------------------- void program_SCANkey(){unsigned char key_code;----------------------------------------------------------------- //函数名称: delay //入口参数:N//函数功能:延时子程序,实现(16*N+24)us 的延时// 系统采用11.0592MHz 的时钟时,延时满足要求,其它情况需要改动// --------------------------------------------------------------------------------------------------void delay(unsigned int N){int i;for(i=0;i<N;i++);}// --------------------// 函数名称:system_init()if(judge_hitkey())(1000);if(judge_hitkey())while(judge_hitkey());key_manage(key_code);// ------------------------------// 判断是否有键按下 {delay //延时20ms 左右,消除抖动干扰 //判断是否有效按键 {key_code=scan_key (;) // 等待按键释放 // 键盘扫描、键盘散转、按键处理 }}}// 函数功能:初始化设置// 设定INT0、INT1 及T0、T1的工作方式// --------------------------------------------------------------------------------------------------/* void system」nit(void ){TMOD=0x55;〃定时器1和定时器0工作在方式1,的计数模式TR0=1; //定时器 1 和定时器0开始计数TR1=1;ET0=1; //定时器1 和定时器0中断允许ET1=1;IT1=0; //选择INTO和INT1为电平触发方式IT0=0;EX0=1; //外部中断允许EX1=0;EA=1; // 系统中断允许}// --------------------------------------------------------------// 函数名称:INT0_intrupt// 函数功能:外部中断0 处理程序//void INT0_intrupt() interrupt 0 using 1{EA=0; // 系统中断禁止delay(1000); // 键盘消抖动if(INT_0==0) // 判断是否干扰{ // 的确有健按下while(INT_O==O);〃等待键盘释放delay(1000); //键盘消抖动manage_key1();}EA=1;}*/// -------------------------------------------------------------------------------------------------- // 函数名称:judge_hitkey// 函数功能:// 判断是否有键按下,有返回1,没有返回0// --------------------------------------------------------------------------------------------------bitjudge_hitkey() // 判断是否有键按下,有返回1,没有返回0{unsigned char scancode,keycode;scancode=0xff; //P1.4~P1.7 输出全 1 则无键闭合 KEY=scancode;// 函数名称:scan_key// 函数功能:// 扫描键盘,返回键值 (高四位代表行,低四位代表列 )// ----------------------------- unsignedcharscan_key() // 扫描键盘,返回键值 (高四位代表 行,低四位代表列 ){unsigned char scancode,keycode;scancode=0xef; // 键盘扫描码,采用逐行扫描的方法 while(scancode!=0xff){KEY=scancode; // 输入扫描 码,扫描 P1.4 对应的行keycode=KEY;1.0~P1.3 的状态if(keycode==0xff)return(0);elsereturn(1);// 读 P // 全 1 则无键闭合 //否则有键闭合 }//if((keycode&0x0f)!=0x0f)keycode=~keycode;return(keycode);}// --------------------------------------------------------------------------- // 函数名称:key_manage// 入口参数:keycode 扫描键盘返回的键值 (高四位代表行,低四位代表列 )// 函数功能: 键盘散转// -------------------------------------------------------------------------------------------------- void key_manage(unsigned char keycode){switch(keycode){case 0x11:manage_key1();break;case 0x12: manage_key2();break;case 0x14: manage_key3();break;case 0x18: manage_key4();break;case 0x21:manage_key5();break;case 0x22: manage_key6();break;case 0x24: manage_key7();break;case 0x28: manage_key8();break;keycode=KEY;列键盘被按下// 读出数据,看是否在此行上的某 break; scancode=(keycode<<1)|0x0f;// 扫描到按下的键,则退出// 否则,更新扫描码继续扫描 }case 0x41:manage_key9();break;case 0x42: manage_key10();break;case 0x44: manage_key11();break;case 0x48: manage_key12();break;case 0x81:manage_key13();break;case 0x82: manage_key14();break;case 0x84: manage_key15();break;case 0x88: manage_key16();break;// default:}}// -------------------------------------------------------------------------------------------------- // 函数名称:manage_key1// 函数功能:按键 1 处理程序// -------------------------------------------------------------------------------------------------- void manage_key1(void){}程序扫描键盘,有键按下完成按键处理,无键按下直接返回。

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--); }。

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

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

4×4矩阵键盘51单片机识别实验与程序1.实验任务图2.硬件电路原理图图3.系统板上硬件连线(1.把“单片机系统“区域中的-端口用8芯排线连接到“4X4行列式键盘”区域中的C1-C4 R1-R4端口上;(2.把“单片机系统”区域中的AD0-AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:AD0对应着a,AD1对应着b,……,AD7对应着h。

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

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

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

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

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

5.程序框图图C语言源程序#include <>unsigned char code table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsigned char temp;unsigned char key;unsigned char i,j;void main(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){case 0x0e:key=7;break;case 0x0d:key=8;break;case 0x0b:key=9;break;case 0x07:key=10;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp & 0x0f; while(temp!=0x0f) {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){case 0x0e:key=4;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07: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;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){case 0x0e:key=1;break;case 0x0d:key=2;break;case 0x0b:key=3;break;case 0x07: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){case 0x0e:key=0;break;case 0x0d:key=13;break;case 0x0b:key=14;break;case 0x07:key=15;break;}temp=P3;P1_0=~P1_0;P0=table[key];temp=temp & 0x0f; while(temp!=0x0f) {temp=P3;temp=temp & 0x0f; }}}}}。

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序以下为一个基于51单片机的矩阵按键扫描的设计C语言程序:```c#include <reg51.h>//定义端口连接到矩阵键盘sbit col1 = P2^0;sbit col2 = P2^1;sbit col3 = P2^2;sbit row1 = P2^3;sbit row2 = P2^4;sbit row3 = P2^5;sbit row4 = P2^6;//声明按键函数char read_keypad(;void maiwhile (1)char key = read_keypad(; // 读取按键值//根据按键值进行相应操作switch(key)case '1'://第一行第一列按键逻辑//在此处添加相应的代码break;case '2'://第一行第二列按键逻辑//在此处添加相应的代码break;//继续处理其他按键//...default://未识别到按键break;}}//按键扫描函数char read_keypacol1 = 0; col2 = 1; col3 = 1; // 激活第一列if (row1 == 0) { // 第一行第一列按键被按下while (row1 == 0); //等待按键释放return '1'; // 返回按键值}if (row2 == 0) { // 第二行第一列按键被按下while (row2 == 0); //等待按键释放return '4'; // 返回按键值}if (row3 == 0) { // 第三行第一列按键被按下while (row3 == 0); //等待按键释放return '7'; // 返回按键值}if (row4 == 0) { // 第四行第一列按键被按下while (row4 == 0); //等待按键释放return '*'; // 返回按键值}col1 = 1; col2 = 0; col3 = 1; // 激活第二列//处理第二列的按键逻辑//...col1 = 1; col2 = 1; col3 = 0; // 激活第三列//处理第三列的按键逻辑//...return '\0'; // 返回空字符表示未检测到按键```以上代码中,我们使用51单片机的P2端口连接到矩阵键盘的列和行,通过扫描不同的列和检测行的状态来判断按键是否被按下。

51单片机的键盘扫描程序

51单片机的键盘扫描程序

一个51单片机的键盘扫描程序,算法简单有效/****************************************键盘_不采用定时器_不延时特点:按键在松手后有效,灵敏度高,消耗资源少,运行效率高独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7;矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0列(左到右)_P2.7_P2.6_P2.5_P2.4提供的操作函数://独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_keyextern unsigned char keyboard_self();//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位extern unsigned char keyboard_matrix();****************************************/先看独立键盘(和矩阵键盘的算法一样)-----------------------------------------------------------------------#include<reg52.h>#include<intrins.h>//独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_keyextern unsigned char keyboard_self(){unsigned char num_key=0;//按键号unsigned char temp=0;//用于读取P2线上按键值static unsigned char temp_code=0;//保存按键值static unsigned char num_check=0;//低电平有效次数static unsigned char key_flag=0;//按键有效标识temp=P2&0xF0;//读取P2线数据if(temp!=0xF0)//低电平判断{num_check++;if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效{key_flag=1;//使能按键有效标识temp_code=temp;//保存按键值}}else//松手时判断{num_check=0;if(key_flag==1)//按键有效{key_flag=0;switch(temp_code)//读取按键号{case 0xE0: num_key=1;break;case 0xD0: num_key=2;break;case 0xB0: num_key=3;break;case 0x70: num_key=4;break;}}}return(num_key);}现在是矩阵键盘的-----------------------------------------------------------------------#include<reg52.h>#include<intrins.h>//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位extern unsigned char keyboard_matrix(){unsigned char num_key=0;//按键号unsigned char temp=0;//读取P2口线数据static unsigned char temp_code=0;//用于保存按键值static unsigned char temp_circle=0xFE;//保存P2线上的循环扫描值static unsigned char num_check=0;//低电平计数static unsigned char key_flag=0;//按键有效标识P2=temp_circle;//0xFXtemp=P2;//读取P2口线数据if(temp!=temp_circle)//有按键动作{num_check++;//低电平计数|逢低电平加1if(num_check==10)//连续10次(10ms)低电平有效{key_flag=1;//按键有效标识置1temp_code=temp;//保存按键值}}else//松手OR无按键动作,此时应该改变扫描线{num_check=0;if(key_flag==1)//按键有效判断{key_flag=0;switch(temp_code)//读取按键号{//P2^0线case 0xEE: num_key=1;break;case 0xDE: num_key=2;break;case 0xBE: num_key=3;break;case 0x7E: num_key=4;break;//P2^1线case 0xED: num_key=5;break;case 0xDD: num_key=6;break;case 0xBD: num_key=7;break;case 0x7D: num_key=8;break;//P2^2线case 0xEB: num_key=9;break;case 0xDB: num_key=10;break;case 0xBB: num_key=11;break;case 0x7B: num_key=12;break;//P2^3线case 0xE7: num_key=13;break;case 0xD7: num_key=14;break;case 0xB7: num_key=15;break;case 0x77: num_key=16;break;}}temp_circle=_crol_(temp_circle,1);//改变扫描线if(temp_circle==0xEF){temp_circle=0xFE;}}return(num_key);//返回按键号}/************************************************************************* 未按键时,扫描线一直变化。

单片机矩阵键盘编码

单片机矩阵键盘编码

单片机矩阵键盘编码是一种常用的输入设备接口技术,它通过将按键矩阵与单片机相连,实现对按键的识别和操作。

在单片机矩阵键盘编码中,常用的编码方式有行列式编码和扫描式编码等。

本文将介绍一种基于行列式编码的单片机矩阵键盘编码方法,以实现按键的识别和操作。

一、按键矩阵电路设计首先,我们需要设计一个按键矩阵电路,该电路由多个按键组成,并使用行线和列线进行连接。

常见的按键矩阵电路有4x4、5x5等不同规格,其中每个按键都通过行线和列线连接到单片机上。

二、行列式编码原理行列式编码是一种基于矩阵的按键编码方式,它通过将按键矩阵中的行线和列线进行编码,实现对按键的识别和操作。

具体来说,我们将按键矩阵中的行线和列线分别连接到单片机的I/O口上,并使用单片机的软件对I/O口的状态进行检测,从而识别出按键的位置和状态。

在行列式编码中,我们通常将行线划分为上、下两行,并将列线划分为左、右两列。

这样,当一个按键被按下时,其所在的行线和列线将同时发生变化。

通过检测行线和列线的状态变化,我们可以确定按键的位置和状态。

三、编码实现方法在实现单片机矩阵键盘编码时,我们需要编写相应的软件程序,对行线和列线的状态进行检测和判断。

通常,我们使用单片机的中断系统来实现按键的实时检测和响应。

具体来说,我们可以在单片机的I/O口上设置相应的中断请求,并在中断服务程序中对行线和列线的状态进行检测和判断。

当一个按键被按下时,其所在的行线和列线将同时发生变化。

我们可以通过比较当前状态和上一次状态的不同来确定按键的位置和状态。

如果某一行或某一列的状态发生变化,则说明有按键被按下。

我们可以通过判断该行或该列的状态变化来确定是哪个按键被按下。

四、总结单片机矩阵键盘编码是一种常用的输入设备接口技术,通过将按键矩阵与单片机相连,实现对按键的识别和操作。

在单片机矩阵键盘编码中,常用的编码方式有行列式编码和扫描式编码等。

本文介绍了一种基于行列式编码的单片机矩阵键盘编码方法,通过将按键矩阵中的行线和列线进行编码,实现对按键的识别和操作。

51单片机按键扫描程序

51单片机按键扫描程序

51单片机按键扫描程序#include#define uint unsigned int#define uchar unsigned charvoid delay(uint z);sbit LE=P1^4;uchar code table[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e};void main(){uchar temp;uint num;while(1){P2=0xfe; //按键扫描第一行temp=P2;temp=temp&0xf0;while(temp!=0xf0){delay(10); //消抖temp=P2;temp=temp&0xf0;while(temp!=0xf0) //再次确认是否有键按下{temp=P2;switch(temp){case 0xee:num=0;break; case 0xde:num=1;break; case 0xbe:num=2;break; case 0x7e:num=3;break;}while(temp!=0xf0) //松手检测{temp=P2;temp=temp&0xf0;}delay(10); //消抖LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xfd; //按键扫描第二行temp=P2;temp=temp&0xf0;while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0;while(temp!=0xf0){temp=P2;switch(temp){case 0xed:num=4;break; case 0xdd:num=5;break; case 0xbd:num=6;break; case 0x7d:num=7;break; }while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xfb; //按键扫描第三行temp=P2;temp=temp&0xf0; while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0; while(temp!=0xf0){temp=P2;switch(temp){case 0xeb:num=8;break; case 0xdb:num=9;break; case 0xbb:num=10;break; case 0x7b:num=11;break; }while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}P2=0xf7; //按键扫描第四行temp=P2;temp=temp&0xf0; while(temp!=0xf0){delay(10);temp=P2;temp=temp&0xf0;while(temp!=0xf0){temp=P2;switch(temp){case 0xe7:num=12;break; case 0xd7:num=13;break; case 0xb7:num=14;break; case 0x77:num=15;break;}while(temp!=0xf0){temp=P2;temp=temp&0xf0;}delay(10);LE=1;P0=table[num];LE=0;P1=0x0f;}}}}void delay(uint z) //延时子函数{uint x;for(z;z>0;z--)for(x=1000;x>0;x--); }。

基于51单片机的利用单片机IO口实现阵列式键盘程序

基于51单片机的利用单片机IO口实现阵列式键盘程序

基于51单片机的利用单片机IO口实现阵列式键盘程序//-----------------------函数声明,变量定义---------------------------#include //头文件#define uchar unsigned char //类型定义#define uint unsigned int //类型定义#define KEY P1//-----------------------函数声明------------------------------------void SCANkey(); //程序扫描键盘,供主程序调用void delay(uint N); //延时子程序,实现(16*N+24)us的延时bit hitkey(); //判断是否有键按下,有返回1,没有返回0 uchar scan_key(); //扫描键盘,返回键值void key_manage(uchar keycode); //键值处理跳转程序void key1(void); //按键1处理程序//……//其它按键处理程序省略//main():主函数//在主函数中,先对系统进行初始化设置,其后主要任务是实时检测有无按键按下,有按键按下时,调用相应处理程序;无按键按下时,继续循环检测。

void main(){EA=0; //关中断while(1) //循环检测按键,调用相应处理程序{SCANkey(); //调用扫描键盘程序}}//SCANkey():扫描键盘程序//扫描键盘程序,有键按下完成按键处理,无键按下直接返回。

void SCANkey(){uchar key_code;if(hitkey()) //判断是否有键按下{delay(1000); //延时20ms左右,消除抖动干扰if(hitkey()) //判断是否有效按键{key_code=scan_key();while(hitkey()); //等待按键释放key_manage(key_code); //键盘扫描、键值处理跳转、按键处理} }}//delay():延时子程序//延时子程序,实现(16*N+24)us的延时。

51单片机行列式键盘程序

51单片机行列式键盘程序

扫描法:以4*4矩阵按键为例,将全部行线置低电平,然后检测列线的状态。

只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。

若所有列线均为高电平,则键盘中无键按下。

判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。

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

在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。

若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

#include "reg52.h"#define uchar unsigned char#define uint unsigned intvoid Delay_1ms(uint i);uchar keyScan(void);void Main(void){uchar keyValue;//存放键值,第一行的第一个为1第二行第一个为5,依次排列while(1){P1 = 0xf0;if(P1 != 0xf0)//判断是否有键按下{Delay_1ms(20);//消除键抖动if(P1 != 0xf0)//在此判断是否有键按下{keyValue = keyScan(); //逐行扫描,判断是哪个按键按下}}//此处用于对不同键值做出不同反应}}uchar keyScan(void){uchar temp,i,j,lineSelect[4]={0xef, 0xdf, 0xbf, 0x7f}; //数组用于线选for(j=0;j<4;j++)//循环四次用于四个行线依次拉低{P1=lineSelect[j];//每根行线依次拉低temp=1;for(i=0;i<4;i++)//循环四次用于判断哪列有键按下{if(!(P1&temp))//判断此列是否有键按下return (i+j*4);//返回键值,行*4+列,行和列的交叉处temp<<=1;//将目标移为下一列}}}void Delay_1ms(uint i)//延时函数{uchar x,j;for(j=0;j<i;j++)for(x=0;x<=148;x++);}线翻转法:Step 1:将列线作为输出线,行线作为输入线。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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

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

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

//行列扫描
#include<reg51.h>
#define GPIO_KEY P0
#define GPIO_LCD P2
unsigned 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 P2
unsigned 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--); }。

相关文档
最新文档