实验六矩阵键盘实验目的1、掌握矩阵键盘的工作原理;2、掌握在一个keil工程中添加多个源文件或库(1ib文件),并调用其他源文件中的函数与全局变量,了解模块化的编程方法。实验设备与文件二、PC机、Stc89c52实验箱、USB线、stc89c52实验板原理图。P30/TXDO120STOS1Ln1P31/RXDsi5S171o0120P32/NTOSI8S2101O1201P33/NT1P34/LCDENP35/RSP36/WRP37/RD矩阵键盘模块图1原理图三、实验原理:矩阵键盘用于按键数目较多的场合,由行线和列线组成,按键位于行、列交叉点上。见图1,一个4×4的行、列结构可以构成一个16个按键的键盘,只需要一个8位的并行I/0口即可。在按键数目较多场合,矩阵式键盘要比独立式键盘节省较多I/0口线。先判有无按键按下,即把所有行线P3.0~P3.3均置为低,然后检测列线状态,若列线不全为高电平,则说明键盘中有按键被按下,并记录为低电平的列号;若所有列线列均为高电平,说明键盘中无按键按下。1
1 实验六 矩阵键盘 一、 实验目的 1、掌握矩阵键盘的工作原理; 2、掌握在一个 keil 工程中添加多个源文件或库(lib 文件),并调用其他源文 件中的函数与全局变量,了解模块化的编程方法。 二、 实验设备与文件 PC 机、stc89c52 实验箱、USB 线、stc89c52 实验板原理图。 图 1 原理图 三、 实验原理: 矩阵键盘用于按键数目较多的场合,由行线和列线组成,按键位于行、列交 叉点上。见图 1,一个 4×4 的行、列结构可以构成一个 16 个按键的键盘,只需 要一个 8 位的并行 I/O 口即可。在按键数目较多场合,矩阵式键盘要比独立式键 盘节省较多 I/O 口线。 先判有无按键按下,即把所有行线 P3.0~P3.3 均置为低,然后检测列线状 态,若列线不全为高电平,则说明键盘中有按键被按下,并记录为低电平的列号; 若所有列线列均为高电平,说明键盘中无按键按下
在确认有按键按下,并记录所在列号后,即可查找具体闭合键的位置,其方法是将列线P3.4~P3.7置为低电平,再检查行线的电平状态。若某行电平为低,则说明该行线与列线交叉处的键值就是按下的键值。四、实验内容及步骤:4.1内容与要求1、利用keil4软件搭建好实验环境;2、P3口请勿外接任何设备、杜邦线等,否则会影响实验效果;3、实现分别按下实验板矩阵键盘上的16个按键,数码管显示不同的数值;4、依照实验参考程序,将delayO函数与leddata数组保存在一个新建的C源文件中,将这个新建的C源文件添加到工程中。通过调用外部函数的方法调用delayO函数,通过访问全局变量的方式访问leddata数组。keil工程中的两个源文件会通过编译程序分别编译生成两个目标文件(.obi),目标文件和库文件(.lib)再通过连接程序生成可执行程序。实验报告中回答以下问题:①C语言中exterm关键字的作用:②查阅资料,说明使用全局变量的缺点。4.2实验步骤(参考)(一)新建文件“mylib.c”,保存在工程文件夹中,存放delay函数:#include“mylib.h"/函数在源文件中定义,在头文件中声明void delay(unsigned int z)1unsigned int x,y,for(x= z, x> 0; x--)for(y = 114; y >0 ; y--),手(二)新建“mylib.c”的头文件“mylib.h”,保存在工程文件夹中:#ifndef_MYLIB_HI/定义_MYLIB_H宏,为了防止头文件被重复包含#defineMYLIBH//这种宏的使用方法比较普遍,请大家掌握externvoiddelay(unsignedint);//在头文件中声明外部函数#endif(三)将“mylib.c”源文件添加到工程项目中,在主程序源文件中添加包含“mylib.h"的语句:include“mylib.h”,即可调用“mylib.c”源文件中的delayO函数。2
2 在确认有按键按下,并记录所在列号后,即可查找具体闭合键的位置,其方 法是将列线 P3.4~P3.7 置为低电平,再检查行线的电平状态。若某行电平为低, 则说明该行线与列线交叉处的键值就是按下的键值。 四、 实验内容及步骤: 4.1 内容与要求 1、 利用 keil4 软件搭建好实验环境; 2、 P3 口请勿外接任何设备、杜邦线等,否则会影响实验效果; 3、 实现分别按下实验板矩阵键盘上的 16 个按键,数码管显示不同的数值; 4、 依照实验参考程序,将 delay()函数与 leddata[]数组保存在一个新建的 C 源文件中,将这个新建的 C 源文件添加到工程中。通过调用外部函数的 方法调用 delay()函数,通过访问全局变量的方式访问 leddata[]数组。keil 工程中的两个源文件会通过编译程序分别编译生成两个目标文件(.obj), 目标文件和库文件(.lib)再通过连接程序生成可执行程序。实验报告中回 答以下问题:①C 语言中 extern 关键字的作用;②查阅资料,说明使用 全局变量的缺点。 4.2 实验步骤(参考) (一)新建文件“mylib.c”,保存在工程文件夹中,存放 delay 函数: #include “mylib.h” void delay(unsigned int z) //函数在源文件中定义,在头文件中声明 { unsigned int x,y; for(x = z; x > 0; x-) for(y = 114; y > 0 ; y-); } (二)新建“mylib.c”的头文件“mylib.h”,保存在工程文件夹中: #ifndef _MYLIB_H //定义_MYLIB_H 宏,为了防止头文件被重复包含 #define _MYLIB_H //这种宏的使用方法比较普遍,请大家掌握 extern void delay(unsigned int); //在头文件中声明外部函数 #endif (三)将“mylib.c”源文件添加到工程项目中, 在主程序源文件中添加包含“mylib.h”的语句:#include “mylib.h”, 即可调用“mylib.c”源文件中的 delay()函数
五、实验参考程序:#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbitwe=P2°7;sbit du = P2'6:uchar KeyValue = 22://按键初始值unsigned char code leddata[]={1/"0"0x3F,//"1"0x06,//"2"0x5B,//"3"0x4F,//"4"0x66,11"5"0x6D,11"6"0x7D,1/"7"0x07,1/"8"0x7F,1/"9"0x6F,II"A"0x77,//"B"0x7C,1I"c"0x39,//"D"0x5E,/I"E"0x79,//"F"0x71,//"H"0x76,1/"L"0x38,//"n"0x37,II"u"0x3E,//"p"0x73,1/"0"0x5C,11"~"0x40,0x00,//熄灭//自定义0x001:void delay(uint z)uint x,y;for(x = z; x>O; x--)for(y=114; y>00 : y--) ;3
3 五、 实验参考程序: #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit we = P2^7; sbit du = P2^6; uchar KeyValue = 22; //按键初始值 unsigned char code leddata[]={ 0x3F, //"0" 0x06, //"1" 0x5B, //"2" 0x4F, //"3" 0x66, //"4" 0x6D, //"5" 0x7D, //"6" 0x07, //"7" 0x7F, //"8" 0x6F, //"9" 0x77, //"A" 0x7C, //"B" 0x39, //"C" 0x5E, //"D" 0x79, //"E" 0x71, //"F" 0x76, //"H" 0x38, //"L" 0x37, //"n" 0x3E, //"u" 0x73, //"P" 0x5C, //"o" 0x40, //"-" 0x00, //熄灭 0x00 //自定义 }; void delay(uint z) { uint x,y; for(x = z; x > 0; x-) for(y = 114; y > 0 ; y-); }
//20个按键的键盘扫描函数和矩阵键盘的扫描函数略有不同//按键扫描函数voidKeyScan1P3=0xfO://判断哪一列被按下if(P3 !=Oxf0)1delay(5);//软件去抖if(P3!=Oxfo)(switch(P3)1case Oxeo:KeyValue = O;break;case Oxdo:KeyValue = l;break;case Oxbo:KeyValue = 2;break;case0x70:KeyValue = 3:break;1//判断哪一行被按下P3 = Ox0f:switch(P3)case OxOe:KeyValue=KeyValue;break;case Oxod:KeyValue += 4;break;//第二行的起始位置是4case OxOb:KeyValue += 8;break;case 0x07:KeyValue +=12:break;1while(P3!=0x0f)://松手检测亨1P3=0xff://判断独立按键if(P3 !=Oxff)fdelay(5) ://软件去抖if(P3 != Oxff)(switch(P3)tcase Oxfe:KeyValue = 16;break;case Oxfd:KeyValue = 17;break;case Oxfb:KeyValue = 18;break;case Oxf7:KeyValue = 19;break;1while(P3!=Oxff)://松手检测14
4 //20 个按键的键盘扫描函数和矩阵键盘的扫描函数略有不同 void KeyScan() //按键扫描函数 { P3 = 0xf0; //判断哪一列被按下 if(P3 != 0xf0) { delay(5); //软件去抖 if( P3 != 0xf0) { switch(P3) { case 0xe0: KeyValue = 0; break; case 0xd0: KeyValue = 1; break; case 0xb0: KeyValue = 2; break; case 0x70: KeyValue = 3; break; } P3 = 0x0f; //判断哪一行被按下 switch(P3) { case 0x0e: KeyValue = KeyValue; break; case 0x0d: KeyValue += 4; break; //第二行的起始位置是 4 case 0x0b: KeyValue += 8; break; case 0x07: KeyValue += 12; break; } while(P3 != 0x0f); //松手检测 } } P3 = 0xff; //判断独立按键 if(P3 != 0xff) { delay(5); //软件去抖 if( P3 != 0xff) { switch(P3) { case 0xfe: KeyValue = 16; break; case 0xfd: KeyValue = 17; break; case 0xfb: KeyValue = 18; break; case 0xf7: KeyValue = 19; break; } while(P3 != 0xff); //松手检测 } } }
void main)we=1://打开位选PO=O;//八位数码管全显示we=0://锁存位选du=1://打开段选PO = 0;while(1)tKeyScan ();PO - leddata[KeyValue] ;1-5
5 void main() { we = 1;//打开位选 P0 = 0;//八位数码管全显示 we = 0;//锁存位选 du = 1;//打开段选 P0 = 0; while(1) { KeyScan(); P0 = leddata[KeyValue]; } }