2499|0

1702

帖子

0

TA的资源

五彩晶圆(初级)

楼主
 

MSP430单片机实例12-4X4矩阵键盘键值显示 [复制链接]

任务要求
将4X4矩阵式键盘编号,如果其中一个按键闭合,则在LED数码管上显示相应的按键编号。

 

分析说明
4X4矩阵键盘只需要占用一个8位的I/O端口,硬件电路的设计较为简单,重点在于如何在程序中判断矩阵键盘的按键位置。

选取MSP430F247单片机的P4端口连接数码管,用以显示按键编号,P5端口8个引脚分别和矩阵式键盘的行线和列线连接,硬件电路如下图所示。

选取MSP430F247单片机的P4端口连接数码管,用以显示按键编号,P5端口8个引脚分别和矩阵式键盘的行线和列线连接,硬件电路如下图所示。

电路图中,列线P5.4~P5.7通过上拉电阻连接电源,处于输入状态;行线P5.0~P5.3为输出状态。键盘上没有按键闭合时,所有列线P5.4~P5.7的输入全部为高电平。当键盘上某个按键闭合时,则对应的行线和列线短接。

在检测是否有键闭合时,先使4条行线全部输出低电平,然后读取4条列线的状态,如果全部为高电平则表示没有任何按键闭合,如果有任一键闭合,由于列线上是上拉电阻,则行线上读到的将是一个非全“1”的值。

确定矩阵式键盘上那个按键闭合通常采用行扫描法,又称为逐行(或列)扫描查询法,其软件主要基于扫描完成。

关于键盘扫描查询法的程序大致可以分为以下几个步骤:

1、检测当前是否有键闭合

首先看输入的列线,假设4条行线都输出低电平,4条列线上都是上拉电阻,在没有任何键闭合时,4条列线输入都为1,但当与某一条行线相连的4个键中的任何一个闭合时,这条列线将输入低电平,即当某条列线输入低电平时,必定是连接在这条裂线上的某个键闭合了。

2、去除按键抖动当检测到有按键闭合后,延长一段时间再做下一步的检测判断。

3、若有键闭合,检测出是哪一个键闭合

逐行扫描方式:在4条行线上分别输出0信号。第一次,在第一条行线上输出低电平,其它行线上输出高电平,第二次,在第二条行线上输出低电平,其它行线上输出高电平,,第三次,在第三条行线上输出低电平,其它行线上输出高电平,,第四次,在第四条行线上输出低电平,其它行线上输出高电平,当某一行线上输出低电平时,此时如果此行上有键被按下,那么相应键的列线上就会读到0,于是可以唯一的确定是那个那键被按下。

//main.c

#include "msp430f247.h"

#include "stdlib.h"

#include "string.h"

/*****************************************软件延时,主频1M*******************/

#define CPU_F1 ((double)1000000)

#define delay_us1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000000.0))

#define delay_ms1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000.0))

/****************************************************************************/

//共阳极数码管段码表

unsigned char const Led_Tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,

0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

//共阴极数码管段码表

unsigned char const Led_Tab2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,

0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

static unsigned char key;

unsigned char KeyScan(void);//

unsigned char GetKeyValue(unsigned char keycode);//

/************************************************

函数名称:主函数

函数功能:矩阵键盘编号显示

入口参数:无

出口参数:无

************************************************/

main()

{

unsigned char key;

WDTCTL = WDTPW + WDTHOLD;//关看门狗

P4DIR=0xff;//端口初始化

P4OUT=0x00;//端口初始化

//行线P5.0~P5.3为输出状态。列线P5.4~P5.7为输入

P5DIR=0x0f;//

while(1)

{

key=GetKeyValue(KeyScan());//显示扫描

if(key != 255)

{

P4OUT=Led_Tab2[key];

}

}

}

unsigned char KeyScan(void)

{

unsigned char ScCode,ReCode;

P5OUT=0x00;

if((P5IN & 0xf0) != 0xf0)//判断是否有键闭合

{

delay_ms1M(40);

if((P5IN & 0xf0) != 0xf0)//延时后再次判断是否有按键闭合,

{

ScCode=0xfe;//逐行扫描初值,先扫描第一行

while((ScCode&0x0f) != 0x0f)//行扫描完成

{

P5OUT=ScCode;//输出行扫描码

if((P5IN & 0xf0) != 0xf0)//当前行有键闭合

{

ReCode=(P5IN & 0xf0) | 0x0f;//读取高4位列值,低4位置1

key=(ScCode & ReCode);//行和列组合得到键盘编码

return key;

}

else//所扫描行没有按键闭合,则扫描下一行

{

ScCode=(ScCode<<1)|0x01;//行扫描码左移一位

}

}

}

return 0xff;//无键按下

}

return 0xff;//无键按下

}

unsigned char GetKeyValue(unsigned char keycode)

{

unsigned char keyval;

switch(keycode)

{

case 0x77:

keyval=0;

break;

case 0x7b:

keyval=1;

break;

case 0x7d:

keyval=2;

break;

case 0x7e:

keyval=3;

break;

case 0xb7:

keyval=4;

break;

case 0xbb:

keyval=5;

break;

case 0xbd:

keyval=6;

break;

case 0xbe:

keyval=7;

break;

case 0xd7:

keyval=8;

break;

case 0xdb:

keyval=9;

break;

case 0xdd:

keyval=10;

break;

case 0xde:

keyval=11;

break;

case 0xe7:

keyval=12;

break;

case 0xeb:

keyval=13;

break;

case 0xed:

keyval=14;

break;

case 0xee:

keyval=15;

break;

default:

keyval=255;

}

return keyval;

}

程序说明
主程序通过调用键盘扫描程序获取键值,并通过数码管显示出键盘编号。键盘扫描首先通过读取列线输入,如果不全是1,则延迟一定时间后再次判断列线是否全为1,如果依旧不全为1,则可以确定有稳定的按键动作,通过逐行扫描的方式得到按键的位置。

从程序上看还存在两个问题,一是按键扫描中延迟去抖需要一定的时间,浪费了单片机的运算资源;二是在扫描得到按键后如果按键闭合不动,主程序会得到多个相同的键值,即重复按键,这种情况可以通过判断按键弹起的动作来解决

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表