您的位置:首页 > 其它

重拾单片机 第一天 矩阵键盘和 独立键盘

2015-10-26 13:21 253 查看
键盘图片:



行扫描法:

1.CPU先使行线P1.0为低,其余行线为高
2.CPU读入输入缓冲器的状态,以确定哪条列线为0状态,若此时P1.7为0,则"C"键按下;若P1.5为0,则"E"键按下
3.若输入缓冲器(列线)状态全部为1,说明P1.0行没有键盘按下,

4.CPU急继续使P1.1为0,其余行线为高,再读入输入缓冲器的状态,以确定哪条列线为0,从而判断是哪个键盘按下
5.当判断那个键盘按下后,程序转入相应的键盘处理程序



行扫描法: 对应程序

/*************************************
// 该程序目的: 通过键盘来控制 LED灯的亮 ,键盘16个, C840D951对应 01234567 的 LED 灯
// 只有8个LED灯,所以剩下的按键其实没有用到
//
**************************************/

#include<reg52.h>
#define uint16 unsigned int
#define uchar8  unsigned char
#define KEYPORT P3
#define LED P1
uchar8  keynum=16;

uchar8 code num[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

/*****************************/
// 函数名称: DelayMS( )
// 函数功能: 延时
// 入口函数: 延时毫秒
// 出口函数: 无
/*********                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             *******************/
void DelayMS(uint16 val)
{
uint16  i,j;
for(i=0;i<val;i++)
for(j=0;j<113;j++);

}

/*****************************/
// 函数名称: ScanKey(void)
// 函数功能: 矩阵键盘扫描
// 入口参数: 无
// 出口参数: 无       , 但是保留了参数 keynum 的值
/*****************************/

void ScanKey(void)
{
uchar8 uctemp;

//  检测第一行
KEYPORT= 0xfe;   // 也就是令 第一行 P3.0为 低电平,其余都为高电平
uctemp=KEYPORT;
if(uctemp!=0xfe)
{
DelayMS(5);               //  去抖延时
uctemp=KEYPORT;
if(uctemp!=0xfe)
{
uctemp=KEYPORT;       // 取键值
switch(uctemp)
{
case 0xee: keynum=0;  break;       // 第一行第一个键按下
case 0xde: keynum=1;  break;
case 0xbe: keynum=2;  break;
case 0x7e: keynum=3;  break;

}
while(KEYPORT!=0xfe);      // 按键释放检测

}

}

//  以下类似 检测 第二行
KEYPORT= 0xfd;   // 也就是令 第二行 P3.1为 低电平,其余都为高电平
uctemp=KEYPORT;
if(uctemp!=0xfd)
{
DelayMS(5);               //  去抖延时
uctemp=KEYPORT;
if(uctemp!=0xfd)
{
uctemp=KEYPORT;       // 取键值
switch(uctemp)
{
case 0xed: keynum=4;  break;       // 第一行第一个键按下
case 0xdd: keynum=5;  break;
case 0xbd: keynum=6;  break;
case 0x7d: keynum=7;  break;

}
while(KEYPORT!=0xfd);      // 按键释放检测

}

}

// 检测第三行

KEYPORT= 0xfb;   // 也就是令 第三行 P3.2为 低电平,其余都为高电平
uctemp=KEYPORT;
if(uctemp!=0xfb)
{
DelayMS(5);               //  去抖延时
uctemp=KEYPORT;
if(uctemp!=0xfb)
{
uctemp=KEYPORT;       // 取键值
switch(uctemp)
{
case 0xeb: keynum=8;  break;       // 第一行第一个键按下
case 0xdb: keynum=9;  break;
case 0xbb: keynum=10;  break;
case 0x7b: keynum=11;  break;

}
while(KEYPORT!=0xfb);      // 按键释放检测

}

}

// 检测第四行

KEYPORT= 0xf7;   // 也就是令 第四行 P3.3为 低电平,其余都为高电平
uctemp=KEYPORT;
if(uctemp!=0xf7)
{
DelayMS(5);               //  去抖延时
uctemp=KEYPORT;
if(uctemp!=0xf7)
{
uctemp=KEYPORT;       // 取键值
switch(uctemp)
{
case 0xe7: keynum=12;  break;       // 第行第一个键按下
case 0xd7: keynum=13;  break;
case 0xb7: keynum=14;  break;
case 0x77: keynum=15;  break;

}
while(KEYPORT!=0xfd);      // 按键释放检测         // 这里不是很理解,为什么还要等待按键释放

}

}

}

/************************************************************/
//    函数名称: Display(void)
//    函数功能: LED亮
//    入口参数: 要显示的是哪一个LED灯亮
//    出口参数: 无
/************************************************************/
void Display(uchar8 val )
{
if(val==16)
{

LED=0xff;   // 都为高电平,没有灯亮  1111 1111
DelayMS(1000);

}
else
{

LED=num[val];

}

}

void main(void)
{
while(1)
{
ScanKey();
Display(keynum);
DelayMS(2000);

}

}


具体实验现象:



可以看出 P3.0 和 P3.5 接通的时候, 第二个LED 灯亮了。验证实验正确。

疑问:

为什么按键需要释放????

为什么按键按下要等待一段时间,然后对应的LED灯才会切换点亮???

按键释放后LED灯依旧亮着
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: