实验三 矩阵键盘
- 格式:docx
- 大小:56.99 KB
- 文档页数:6
实验五矩阵键盘实验一、实验内容1、编写程序,做到在键盘上每按一个数字键(0-F)用发光二极管将该代码显示出来。
按其它键退出。
2、加法设计计算器,实验板上有12个按键,编写程序,实现一位整数加法运算功能。
可定义“A”键为“+”键,“B”键为“=”键。
二、实验目的1、学习独立式按键的查询识别方法。
2、非编码矩阵键盘的行反转法识别方法。
三、实验说明1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。
2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。
3、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。
这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。
由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。
行反转法识别按键的过程是:首先,将4个行线作为输出,将其全部置0,4个列线作为输入,将其全部置1,也就是向P1口写入0xF0;假如此时没有人按键,从P1口读出的值应仍为0xF0;假如此时1、4、7、0四个键中有一个键被按下,则P1.6被拉低,从P1口读出的值为0xB0;为了确定是这四个键中哪一个被按下,可将刚才从P1口读出的数的低四位置1后再写入P1口,即将0xBF写入P1口,使P1.6为低,其余均为高,若此时被按下的键是“4”,则P1.1被拉低,从P1口读出的值为0xBE;这样,当只有一个键被按下时,每一个键只有唯一的反转码,事先为12个键的反转码建一个表,通过查表就可知道是哪个键被按下了。
实验二阵列式键盘实验一、实验目的1.掌握键盘和显示器的接口方法和编程方法2.掌握阵列式键盘的硬件组成和软件编程方法二、实验说明本实验提供了一个4X4小建盘,向P0口的低四位逐个输出低电平,如果有键盘按下,则相应输出为低,如果没有键按下,则输出为高。
通过输出的列码和读取的行码来判断按下什么键。
有键按下后,要有一定的延时,防止由于键盘抖动而引起误操作。
三、实验步骤及内容1.用一根8位数据线连接阵列式键盘实验模块与LED与单片机接口模块。
无键按下或有键按下,发光二极管全亮。
若将A1-A4接地,则发光二极管显示0000XXXX;B1线上有键按下,则发光二极管显示0000XXX,B2线上有键按下,则发光二极管现世0000X0XX,B1和B2均有键按下,则发光二极管显示000000XX……同样可将B1与B4接地,按键与发光二极管显示情况,用户可以自行判断,自由操作。
2.用一根8位数据线连接阵列式键盘实验模块与扫描显示实验模块。
无键按下或有键按下,八段LED全亮。
用户参照1,观察键盘与八段LED亮熄的关系。
3.使用静态串行显示模块显示键值。
单片机最小应用系统1的P1口接阵列式键盘的A1~B4口,P3.6接静态数码显示DIN,P3.7接CLK。
4.用串行数据通信线连接计算机与仿真器,把仿真器插到模块的锁紧插座中,请注意仿真器的方向:缺口朝上。
5.打开Keil uVision2仿真软件,首先建立本实验的项目文件,接着添加阵列KEY.ASM源程序,进行编译,直到编译无误。
6.进行软件设置,选择硬件仿真,选择串行口,设置波特率为38400。
在键盘上按下某个键,观察数显是否与按键值一致。
16位建盘的键值从左至右、从上至下依次为0~F(16进制数)。
四、流程图及源程序1.流程图主程序框图2.源程序DBUF EQU 30HTEMP EQU 40HDIN BIT P3.6CLK BIT P3.7ORG 0000HLJMP STARTORG 0030HSTART:MOV A,#16MAIN: ACALL DISPMOV 30H, AACALL KEY1AJMP MAINKEY1: MOV P1, #0FH ;A1-A4输出,B1-B4输入,输;入者对应锁存先写“1”MOV A, P1 ;读取键盘状况CJNE A,#0FH, K11 ;有键按下K10: AJMP KEY1 ;无键按下K11: ACALL DELAY ;去抖动MOV P1, #0FHMOV A, P1 ;再读键盘状况CJNE A, #0FH, K12 ;确有键盘按下SJMP K10 ;误动作K12: MOV B,A ;存列值MOV P1, #0EFH ;按键在Ai行MOV A, P1CJNE A, #0EFH,K13 ;键在A4MOV P1, #0DFHMOV A, P1CJNE A, #0DFH,K13 ;键在A3行MOV P1, #0BFHMOV A,P1CJNE A, #0BFH,K13 ;键在A2行MOV P1, #7FHMOV A, P1CJNE A,#7FH, K13 ;键在A1行AJMP K10 ;多键同时按下K13: ANL A, #0F0H ;的行值ORL A, B ;的按下键的行列值MOV B, A ;暂存键值MOV R1, #16 ;16个键MOV R2, #0 ;键码初值MOV DPTR,#K1TAB ;键码表首址K14: MOV A,R2MOVC A, @A+DPTR ;从键值表中取键值CJNE A, B, K16 ;与按下键,键值比较MOV P1,#0FH ;相等,则完成以下步骤K15: MOV A, P1CJNE A, #0FH, K15 ;等释放ACALL DELAY ;去抖动MOV A, R2 ;得键码RETK16: INC R2 ;不相等,则继续访问键值表DJNZ R1,K14AJMP K10 ;多键同时按下处理K1TAB: DB 0EEH, 0DEH, 0BEH, 07EH ;键值表DB 0EDH, 0DDH, 0BDH, 07DHDB 0EBH, 0DBH, 0BBH, 07BHDB 0E7H, 0D7H, 0B7H, 077HDISP: MOV DBUF,AMOV DBUF+1,#16MOV DBUF+2,#16MOV DBUF+3,#16MOV DBUF+4,#16MOV R0, #DBUFMOV R1, #TEMPMOV R2, #5DP10: MOV DPTR,#SEGTABMOV A, @R0MOVC A, @A+DPTRMOV @R1, AINC R0INC R1DJNZ R2, DP10MOV R0, #TEMPMOV R1, #5DP12: MOV R2, #8MOV A, @R0DP13: RLC AMOV 0B0H,CCLR 0B1HSETB 0B1HDJNZ R2, DP13INC R0DJNZ R1, DP12RETSEGTAB: ;段码表DB 3FH,06H,5BH,4FH,66H,6DH ;“0,1,2,3,4,5”DB 7DH,07H,7FH,6FH,77H,7CH ;“6,7,8,9,A,b”DB 58H,5EH,79H,71H,00H,40H ;“C,d,E,F,,-”DELAY: MOV R4, #02HAA1: MOV R5,#0F8HAA: NOPDJNZ R5,AADJNZ R4,AA1RETEND。
* 实验名 : 矩阵键盘实验* 使用的IO : 数码管使用P0,键盘使用P3.0、P3.1、P3.2、P3.3 * 实验效果 : 按矩阵键盘分别显示在数码管上面显示十六进制的0到F。
* 注意:***************************************************************** **************/#include<reg51.h>#include"lcd.h"unsigned char PuZh[]=" Pechin Science ";/**************************************************************** **************** 函数名 : main* 函数功能 : 主函数* 输入 : 无* 输出 : 无***************************************************************** **************/void main(void){unsigned char i;LcdInit();for(i=0;i<16;i++){LcdWriteData(PuZh[i]);}while(1){}}#include"lcd.h"/**************************************************************** **************** 函数名 : Lcd1602_Delay1ms* 函数功能 : 延时函数,延时1ms* 输入 : c* 输出 : 无* 说名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
***************************************************************** **************/void Lcd1602_Delay1ms(uint c) //误差 0us{uchar a,b;for (; c>0; c--){for (b=199;b>0;b--){for(a=1;a>0;a--);}}}/**************************************************************** **************** 函数名 : LcdWriteCom* 函数功能 : 向LCD写入一个字节的命令* 输入 : com* 输出 : 无***************************************************************** **************/#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时void LcdWriteCom(uchar com) //写入命令{LCD1602_E = 0; //使能LCD1602_RS = 0; //选择发送命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //放入命令Lcd1602_Delay1ms(1); //等待数据稳定LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;}#elsevoid LcdWriteCom(uchar com) //写入命令{LCD1602_E = 0; //使能清零LCD1602_RS = 0; //选择写入命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;// Lcd1602_Delay1ms(1);LCD1602_DATAPINS = com << 4; //发送低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;}#endif/**************************************************************** **************** 函数名 : LcdWriteData* 函数功能 : 向LCD写入一个字节的数据* 输入 : dat* 输出 : 无***************************************************************** **************/#ifndef LCD1602_4PINSvoid LcdWriteData(uchar dat) //写入数据{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择输入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //写入数据Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;}#elsevoid LcdWriteData(uchar dat) //写入数据{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择写入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;LCD1602_DATAPINS = dat << 4; //写入低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;}#endif/**************************************************************** **************** 函数名 : LcdInit()* 函数功能 : 初始化LCD屏* 输入 : 无* 输出 : 无***************************************************************** **************/#ifndef LCD1602_4PINSvoid LcdInit() //LCD初始化子程序{LcdWriteCom(0x38); //开显示LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点}#elsevoid LcdInit() //LCD初始化子程序{LcdWriteCom(0x32); //将8位总线转为4位总线LcdWriteCom(0x28); //在四位线下的初始化LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点}#endif#ifndef __LCD_H_#define __LCD_H_/**********************************当使用的是4位数据传输的时候定义,使用8位取消这个定义**********************************/#define LCD1602_4PINS/**********************************包含头文件**********************************/#include<reg51.h>//---重定义关键词---//#ifndef uchar#define uchar unsigned char#endif#ifndef uint#define uint unsigned int#endif/**********************************PIN口定义**********************************/#define LCD1602_DATAPINS P0sbit LCD1602_E=P2^7;sbit LCD1602_RW=P2^5;sbit LCD1602_RS=P2^6;/**********************************函数声明**********************************//*在51单片机12MHZ时钟下的延时函数*/void Lcd1602_Delay1ms(uint c); //误差 0us /*LCD1602写入8位命令子函数*/void LcdWriteCom(uchar com);/*LCD1602写入8位数据子函数*/void LcdWriteData(uchar dat) ;/*LCD1602初始化子程序*/void LcdInit();#endif。
单片机矩阵键盘实验实验报告一、实验目的本次实验的目的是掌握原理和方法,利用单片机识别矩阵键盘并编程实现键码转换功能,控制LED点亮显示。
二、实验原理矩阵键盘是一种由多路单向控制器输入行选择信号与列选择信号连接而形成的一一对应矩阵排列结构。
它广泛应用于电子游戏机、办公自动化设备、医疗仪器、家电控制及书籍检索机器等方面。
本次实验采用的矩阵键盘是一个4 x 4矩阵,用4段数码管显示按键编码,每个按键都可以输入一个代码,矩阵键盘连接单片机,实现一个软件算法来识别键码转化。
从而将键盘中的按键的按下信号转换成程序能够识别的代码,置于相应的输出结果中,控制LED点亮,从而可以实现矩阵键盘按键的转换功能。
三、实验方法1.硬件搭建:矩阵键盘(4行4列)与单片机(Atmel AT89C51)相连,选择引脚连接,并将数码管和LED与单片机相连以实现显示和点亮的功能。
2.程序设计:先建立控制体系,利用中断服务子程序识别和码值转换,利用中断服务子程序实现从按键的按下信号转换为程序能够识别的代码,然后将该代码段编写到单片机程序中,每次按下矩阵键盘按键后单片机给出相应的按键编码输出,用数码管显示,控制LED点亮。
四、实验结果经过实验,成功实现了矩阵键盘与单片机之间的连接,编写了中断服务子程序,完成了按键编码输出与LED点亮的功能。
实验完成后,数码管显示各种按键的编码,同时LED会点亮。
本次实验介绍了矩阵键盘的原理,论述了键码转换的程序设计步骤,并实验完成矩阵键盘与单片机的连接,实现用LED点亮以及数码管显示按键的编码。
通过本次实验,受益匪浅,使我对使用单片机编写算法与程序有了更深入的认识,同时丰富了课堂学习的内容,也使我更加热爱自己所学的专业。
单片机c语言程序设计---矩阵式键盘实验报告课程名称:单片机c语言设计实验类型:设计型实验实验项目名称:矩阵式键盘实验一、实验目的和要求1.掌握矩阵式键盘结构2.掌握矩阵式键盘工作原理3.掌握矩阵式键盘的两种常用编程方法,即扫描法和反转法二、实验内容和原理实验1.矩阵式键盘实验功能:用数码管显示4*4矩阵式键盘的按键值,当K1按下后,数码管显示数字0,当K2按下后,显示为1,以此类推,当按下K16,显示F。
(1)硬件设计电路原理图如下仿真所需元器件(2)proteus仿真通过Keil编译后,利用protues软件进行仿真。
在protues ISIS 编译环境中绘制仿真电路图,将编译好的“xxx.hex”文件加入AT89C51。
启动仿真,观察仿真结果。
操作方完成矩阵式键盘实验。
具体包括绘制仿真电路图、编写c源程序(反转法和扫描法)、进行仿真并观察仿真结果,需要保存原理图截图,保存c源程序,总结观察的仿真结果。
完成思考题。
三、实验方法与实验步骤1.按照硬件设计在protues上按照所给硬件设计绘制电路图。
2.在keil上进行编译后生成“xxx.hex”文件。
3.编译好的“xxx.hex”文件加入AT89C51。
启动仿真,观察仿真结果。
四、实验结果与分析void Scan_line()//扫描行{Delay(10);//消抖switch ( P1 ){case 0x0e: i=1;break;case 0x0d: i=2;break;case 0x0b: i=3;break;case 0x07: i=4;break;default: i=0;//未按下break;}}void Scan_list()//扫描列{Delay(10);//消抖switch ( P1 ){case 0x70: j=1;break;case 0xb0: j=2;break;case 0xd0: j=3;break;case 0xe0: j=4;break;default: j=0;//未按下break;}}void Show_Key(){if( i != 0 && j != 0 ) P0=table[ ( i - 1 ) * 4 + j - 1 ];else P0=0xff;}五、讨论和心得。
单片机实验报告信息处理实验实验二矩阵键盘专业:电气工程及其自动化指导老师:***组员:明洪开张鸿伟张谦赵智奇学号:152703117 \152703115\152703118\152703114室温:18 ℃日期:2017 年10 月25日矩阵键盘一、实验内容1、编写程序,做到在键盘上每按一个键(0-F)用数码管将该建对应的名字显示出来。
按其它键没有结果。
二、实验目的1、学习独立式按键的查询识别方法。
2、非编码矩阵键盘的行反转法识别方法。
3、掌握键盘接口的基本特点,了解独立键盘和矩阵键盘的应用方法。
4、掌握键盘接口的硬件设计方法,软件程序设计和贴士排错能力。
5、掌握利用Keil51软件对程序进行编译。
6、会根据实际功能,正确选择单片机功能接线,编制正确程序。
对实验结果能做出分析和解释,能写出符合规格的实验报告。
三、实验原理1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。
2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。
3、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。
这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。
由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。
实验三:矩阵键盘扫描及LED数码显示综合实验
一、实验要求
利用4×4键盘和一个LED数码管构成简单的输入显示系统,实现键盘输入和LED数码显示相应键值的功能。
二、实验目的
1.掌握数码管显示原理,及无译码显示电路的显示程序的编写;
1.理解矩阵键盘扫描的原理;
2.掌握矩阵键盘与51单片机接口的编程方法。
三、实验电路图
四、主要知识点
键盘扫描原理、无译码电路的显示原理。
五、实验流程图
六、实验效果:点击相应按键显示相应的键值
七、实验步骤
1.在keil环境下编写程序,汇编后生成*.Hex文件。
2.硬件验证
1)用ISP下载*.HEX程序到CPU
2)按连接表连接电路
3)检查验证结果。
八、连线表
十、源程序:自己编写源程序。
矩阵键盘实验报告佘成刚学号2010302001班级08041202时间2016.01.20一、实验目的1.学习矩列式键盘工作原理;2.学习矩列式接口的程序设计。
二、实验设备普中HC6800ESV20开发板三、实验要求要现:用4*4矩阵键盘,用按键形式输入学号,在数码管上显示对应学号。
四、实验原理工作原理:矩阵式由行线和列线组成,按键位于行、列的交叉点上。
如图所示,一个4*4 的行、列结构可以构成一个由16 个按键的键盘。
很明显,在按键数量较多的场合,矩阵式键盘与独立式键盘相比,要节省很多的I/0 口。
(1)矩阵式键盘工作原理按键设置在行、列交节点上,行、列分别连接到按键开关的两端。
行线通过下拉电阻接到GND 上。
平时无按键动作时,行线处于低电平状态,而当有按键按下时,行线电平状态将由与此行线相连的列线电平决定。
列线电平如果为低,行线电平为高,列线电平如果为高,则行线电平则为低。
这一点是识别矩阵式键盘是否被按下的关键所在。
因此,各按键彼此将相互发生影响,所以必须将行、列线信号配合起来并作适当的处理,才能确定闭合键的位置。
(2)按键识别方法下面以3 号键被按下为例,来说明此键是如何被识别出来的。
前已述及,键被按下时,与此键相连的行线电平将由与此键相连的列线电平决定,而行线电平在无键按下时处于高电平状态。
如果让所有列线处于高电平那么键按下与否不会引起行线电平的状态变化,始终是高电平,所以,让所有列线处于高电平是没法识别出按键的。
现在反过来,让所有列线处于低电平,很明显,按下的键所在行电平将也被置为低电平,根据此变化,便能判定该行一定有键被按下。
但我们还不能确定是这一行的哪个键被按下。
所以,为了进一步判定到底是哪—列的键被按下,可在某一时刻只让一条列线处于低电平,而其余所有列线处于高电平。
当第1 列为低电平,其余各列为高电平时,因为是键3 被按下,所以第1 行仍处于高电平状态;当第2 列为低电平,其余各列为高电平时,同样我们会发现第1 行仍处于高电平状态,直到让第4 列为低电平,其余各列为高电平时,因为是3 号键被按下,所以第1 行的高电平转换到第4 列所处的低电平,据此,我们确信第1 行第4 列交叉点处的按键即3 号键被按下。
计算机原理实验室实验报告课程名称:姓名学号班级成绩设备名称及软件环境实验名称矩阵键盘实验日期一.实验内容掌握4×4矩阵式键盘程序识别原理及4×4矩阵式键盘按键的设计方法。
二.理论分析或算法分析用单片机的并行口P3连接4×4矩阵键盘,并以单片机的P3.0-P3.3各管脚作输入线,以单片机的P3.4-P3.7各管脚作输出线,在数码管上显示每个按键“0-F”的序号。
4×4矩阵式键盘识别电路原理图:键盘中对应按键的序号排列:电路硬件说明(1)在“单片机系统”区域中,把单片机的P3.0-P3.7端口通过8联拨动拨码开关JP3连接到“4×4行列式键盘”区域中的M1-M4,N1-N4端口上。
(2)在“单片机系统”区域中,把单片机的P0.0-P0.7端口连接到“静态数码显示模块”区域中的任何一个a-h端口上;要求:P0.0对应着a,P0.1对应着b,……,P0.7对应着h。
三.实现方法(含实现思路、程序流程图、实验电路图和源程序列表等)1、4×4矩阵键盘识别处理。
2、每个按键都有它的行值和列值,行值和列值的组合就是识别这个按键的编码。
矩阵的行线和列线分别通过两并行接口和CPU通信。
键盘的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么?还要消除按键在闭合或断开时的抖动。
两个并行口中,一个输出扫描码,使按键逐行动态接地;另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
3、程序流程图:4、汇编源程序:;;;;;;;;;;定义单元;;;;;;;;;;COUNT EQU 30H;;;;;;;;;;入口地址;;;;;;;;;;ORG 0000HLJMP STARTORG 0003HRETIORG 000BHRETIORG 0013HRETIORG 001BHRETIORG 0023HRETIORG 002BHRETI;;;;;;;;;;主程序入口;;;;;;;;;;ORG 0100H START: LCALL CHUSHIHUALCALL PANDUANLCALL XIANSHILJMP START ;;;;;;;;;;初始化程序;;;;;;;;;;CHUSHIHUA: MOV COUNT,#00HRET;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;;PANDUAN: MOV P3,#0FFHCLR P3.4MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW1LCALL DELAY10MSJZ SW1MOV A,P3ANL A,#0FHCJNE A,#0EH,K1MOV COUNT,#0LJMP DKK1: CJNE A,#0DH,K2MOV COUNT,#4LJMP DKK2: CJNE A,#0BH,K3MOV COUNT,#12 K4: NOPLJMP DKSW1: MOV P3,#0FFHCLR P3.5MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW2LCALL DELAY10MS JZ SW2MOV A,P3ANL A,#0FHCJNE A,#0EH,K5 MOV COUNT,#1 LJMP DKK5: CJNE A,#0DH,K6MOV COUNT,#5 LJMP DKK6: CJNE A,#0BH,K7MOV COUNT,#9 LJMP DKK7: CJNE A,#07H,K8MOV COUNT,#13 K8: NOPLJMP DKSW2: MOV P3,#0FFHCLR P3.6MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW3LCALL DELAY10MS JZ SW3MOV A,P3ANL A,#0FHCJNE A,#0EH,K9 MOV COUNT,#2 LJMP DKK9: CJNE A,#0DH,KAMOV COUNT,#6 LJMP DKKA: CJNE A,#0BH,KBMOV COUNT,#14 KC: NOPLJMP DKSW3: MOV P3,#0FFHCLR P3.7MOV A,P3ANL A,#0FHXRL A,#0FHJZ SW4LCALL DELAY10MS JZ SW4MOV A,P3ANL A,#0FHCJNE A,#0EH,KD MOV COUNT,#3LJMP DKKD: CJNE A,#0DH,KEMOV COUNT,#7LJMP DKKE: CJNE A,#0BH,KFMOV COUNT,#11 LJMP DKKF: CJNE A,#07H,KGMOV COUNT,#15 KG: NOPLJMP DKSW4: LJMP PANDUANDK: RET;;;;;;;;;;显示程序;;;;;;;;;;XIANSHI: MOV A,COUNTMOV DPTR,#TABLE MOVC A,@A+DPTR MOV P0,ALCALL DELAYSK: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ SKRET;;;;;;;;;;10ms延时程序;;;;;;;;;;DELAY10MS: MOV R6,#20D1: MOV R7,#248DJNZ R6,D1RET;;;;;;;;;;200ms延时程序;;;;;;;;;;DELAY: MOV R5,#20LOOP: LCALL DELAY10MSDJNZ R5,LOOPRET;;;;;;;;;;共阴码表;;;;;;;;;;TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07HDB 7FH,6FH,77H,7CH,39H,5EH,79H,71H;;;;;;;;;;结束标志;;;;;;;;;;END八、C语言源程序#include<AT89X51.H>unsigned char code table[]={0x3f,0x66,0x7f,0x39,0x06,0x6d,0x6f,0x5e,0x5b,0x7d,0x77,0x79,0x4f,0x07,0x7c,0x71};void main(void){ unsigned char i,j,k,key;while(1){ P3=0xff; //给P3口置1//P3_4=0; //给P3.4这条线送入0//i=P3;i=i&0x0f; //屏蔽低四位//if(i!=0x0f) //看是否有按键按下//{ for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);if(i!=0x0f) //再次判断按键是否按下//{ switch(i) //看是和P3.4相连的四个按键中的哪个// { case 0x0e:key=0;break;case 0x0d:key=1;break;case 0x0b:key=2;break;case 0x07:key=3;break;}P0=table[key]; //送数到P0口显示//}P3=0xff;P3_5=0; //读P3.5这条线//i=P3;i=i&0x0f; //屏蔽P3口的低四位//if(i!=0x0f) //读P3.5这条线上看是否有按键按下// { for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);i=P3; //再看是否有按键真的按下//i=i&0x0f;if(i!=0x0f){ switch(i) //如果有,显示相应的按键//{ case 0x0e:key=4;break;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}P0=table[key]; //送入P0口显示//}}P3=0xff;P3_6=0; //读P3.6这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=8;break;case 0x0d:key=9;break;case 0x0b:break;case 0x07:key=11;break;}P0=table[key];}}P3=0xff;P3_7=0; //读P3.7这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=12;break;case 0x0d:key=13;break;case 0x0b:key=14;break;case 0x07:key=15;break;}P0=table[key];}}}}四.实验结果分析(含执行结果验证、输出显示信息、图形、调试过程中所遇的问题及处理方法等)五.结论报告提交日期(注意:内容写不下时允许表格添加新行。
实验三矩阵键盘独立键盘与单片机连接时,每一个按键都需要单片机的一个I/O口若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O口资源。
单片机系统中I/O口资源往往比较宝贵,当用到多个按键时为了节省I/O口口线,我们引入矩阵键盘。
我们以4X4矩阵键盘为例讲解其工作原理和检测方法。
将16个按键排成4行4列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,这样便一共有4行4列共8根线,我们将这8根线连接到单片机的8个I/O口上,通过程序扫描键盘就可检测16个键。
用这种方法我们也可实现3行3列9个键、5行5列25个键、6行6列36个键等。
无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的I/O口是否为低电平。
独立键盘有一端固定为低电平,单片机写程序检测时比较方便。
而矩阵键盘两端都与单片机I/O口相连,因此在检测时需人为通过单片机I/O口送出低电平。
检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。
当然我们也可以将行线置低电平,扫描列是否有低电平。
这就是矩阵键盘检测的原理和方法。
首先看一下电路图上图是一个4X4 的矩阵键盘,一共是16 个按键。
我们照习惯称横为“行”,“竖”为列。
那么5、6、7、8 我们称之为“行线”,则1、2、3、4 称为“列线”。
要正确记住各个行列线各自对应的I/O 。
注意看,每一个按键的两端,都分别接在某一个列线和行线上,即:“行线和列线是通过某个按键的按下和抬起实现联通和断开的”。
现在详细讲述一下矩阵键盘扫描的原理和步骤:扫描矩阵键盘,即是把某一条(只有一条)行线置为低电平,而列线全部置为输入方向,然后检测列线,如果检测到某一条列线是低电平,那么就表示位于这条列线与输出低电平的行线的交点处的按键被按下了。
要扫描16个按键,就依次以这样的方法扫描16次,之后就可以确定哪一个按键被按下了。
当然这里也少不了延时消除按键抖动的环节。
下面看一下程序/****************************************************************************** * 实验名 : 矩阵键盘实验* 使用的IO : 数码管使用P0,键盘使用P1* 实验效果 : 按矩阵键盘分别显示在数码管上面显示十六进制的0到F 。
* 注意 :******************************************************************************/ #include<reg51.h>#define GPIO_DIG P0#define GPIO_KEY P1sbit LSA=P2^2; 5 6 7 8 1 2 3 4sbit LSB=P2^3;sbit LSC=P2^4;unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码unsigned char KeyValue;//用来存放读取到的键值void Delay10ms(); //延时10ms函数void KeyDown(); //检测按键函数/***************************************************************************** * 函数名 : main* 函数功能 : 主函数* 输入 : 无* 输出 : 无******************************************************************************/ void main(void){LSA=0; //给一个数码管提供位选LSB=0;LSC=0;while(1){KeyDown();GPIO_DIG=DIG_CODE[KeyValue];}}/****************************************************************************** * 函数名 : KeyDown* 函数功能 : 检测有按键按下并读取键值* 输入 : 无* 输出 : 无******************************************************************************/ void KeyDown(void){char a;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f){Delay10ms();if(GPIO_KEY!=0x0f){//测试列GPIO_KEY=0X0F;switch(GPIO_KEY){case(0X07): KeyValue=0;break;case(0X0b): KeyValue=1;break;case(0X0d): KeyValue=2;break;case(0X0e): KeyValue=3;break;}//测试行GPIO_KEY=0XF0;switch(GPIO_KEY){case(0X70): KeyValue=KeyValue;break;case(0Xb0): KeyValue=KeyValue+4;break;case(0Xd0): KeyValue=KeyValue+8;break;case(0Xe0): KeyValue=KeyValue+12;break;}while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测{Delay10ms();a++;}a=0;}}}/****************************************************************************** * 函数名 : Delay10ms* 函数功能 : 延时函数,延时10ms* 输入 : 无* 输出 : 无******************************************************************************/ void Delay10ms(void) //误差 0us{unsigned char a,b,c;for(c=1;c>0;c--)for(b=38;b>0;b--)for(a=130;a>0;a--);}下载HEX文件,观察实验效果,实验的效果是:按矩阵键盘分别显示在数码管上面显示十六进制的0到F。
ORG 00HLJMP INITORG 30HDB 03FH,006H,05BH,04FH,066H,06DH,07DH,007HDB 07FH,06FH,077H,07CH,039H,05EH,079H,071H ;0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ;*************;; 主程序;;*************;INIT: CLR P2.2CLR P2.3CLR P2.4MOV R1,#00HSTART: MOV A,R1MOV DPTR,#30HMOVC A,@A+DPTRMAIN: MOV P0,A;**********************;; 矩阵键盘扫描程序;;**********************;KEY_SCAN: MOV P1,#00FHNOPMOV R2,P1CJNE R2,#00FH,KEY_DOWN ;没有按键按下就返回主函数SJMP MAINKEY_DOWN: ACALL DELAY10MS ;消抖MOV R2,P1CJNE R2,#00FH,NEXT0SJMP MAIN ;没有按键按下就返回主函数NEXT0: CJNE R2,#007H,NEXT1 ;如果不等于007H就跳去检测下一个键值MOV R1,#00H ;如果是的话SJMP NEXT_SCANNEXT1: CJNE R2,#00BH,NEXT2MOV R1,#01HSJMP NEXT_SCANNEXT2: CJNE R2,#00DH,NEXT3MOV R1,#02HSJMP NEXT_SCANNEXT3: CJNE R2,#00EH,MAINMOV R1,#03HNEXT_SCAN: MOV P1,#0F0HMOV R2,P1CJNE R2,#070H,NEXT4MOV A,#00HADD A,R1MOV R1,ALJMP STARTNEXT4: CJNE R2,#0B0H,NEXT5MOV A,#04HADD A,R1MOV R1,ALJMP STARTNEXT5: CJNE R2,#0D0H,NEXT6MOV A,#08HADD A,R1MOV R1,ALJMP STARTNEXT6: CJNE R2,#0E0H,MAINMOV A,#0CHADD A,R1MOV R1,AMOV R3,#030HKEY_UP: ACALL DELAY10MSDJNZ R3,KEY_UPLJMP START;*************;; 延时程序;;*************;DELAY10MS: MOV R6,#015HDE1: MOV R7,#0F8HDE2: DJNZ R7,DE2DJNZ R6,DE1RETEND。