基于单片机4×4键盘的实现
成员:刘耀鹏、高攀、谢富田
2014年7月20日
理论分析
本实验是基于AT89C52单片机来实现4×4阵列键盘的输入,用七段数码管输出相应的键值,从而提供良好的人机接口。
AT89C52单片机是一个8位的单片,与51系列单片机相比较,其最大的区别是多了一个计数定是中断。
采用12MHz的晶振,采用内接法,对电路提供一个时间基准,P1端口作为键盘的输入端口,P0端口为数据输出端口,P1端口输入的键值,在P0端口产生相应的输出。
4×4键盘被抽象为16个开关按钮(每行4个共四行),那么久有4位行控制线,和列四位控制线,当开关接通时,则按键按下,数码管显示相应的键值,具体硬件电路如下:
电路中排阻限流作用,以达到对数码管保护作用,P2口作为位选端口,数码管8接P2.0端口,数码管7接P0.1端口。
以达到位选
的作用,对于电路可编写一下程序:
2、程序如下:
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
//uchar code table[10] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f, 0x01, 0x09};
uchar code table[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
/********************************************************** ****
* 名称: Delay_1ms()
* 功能: 延时子程序,延时时间为1ms * x
* 输入: x (延时一毫秒的个数)
* 输出: 无
*********************************************************** ****/
void Delay_1ms(uint x)
{
uint i;
uchar j;
for(i = 0; i < x; i++) for(j = 0; j <= 148; j++);
}
/********************************************************** ****
* 名称:Keyscan()
* 功能:P1外接4×4按键, 按照扫描法读出键值
* 输出:按键值0~15/如无键按下, 返回16
*********************************************************** ****/
uchar Keyscan(void)
{
uchar i, j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};
for(j = 0; j < 4; j++) { //循环四次
P1 = Buffer[j]; //在P1高四位分别输出一个低电平
temp = 0x01; //计划先判断P1.0位
for(i = 0; i < 4; i++) { //循环四次
if(!(P1 & temp)) //从P1低四位,截取1位
return (i + j * 4); //返回取得的按键值
temp <<= 1; //判断的位,左移一位
} }
return 16; //判断结束,没有键按下,返回16
}
/********************************************************** ****
* 名称:Display(uchar k)
* 功能:将参数分成十位、个位分别显示
* 输入:k (键盘数值)
* 输出:P0口输出七段码,P2口输出位选码
*********************************************************** ****/
void Display(uchar k)
{
P2 = 1111; //消隐
P0 = table[k / 10];
P2 = 0xfd; Delay_1ms(5); //显示5ms十位
P2 = 1111; //消隐
P0 = table[k % 10];
P2 = 0xfe; Delay_1ms(5); //显示5ms个位
}
/********************************************************** ****
* 名称: Main()
* 功能: 主函数
***********************************************************
****/
void Main(void)
{
uchar Key_Value = 16, Key_Temp1, Key_Temp2; //两次读出的键值
while(1) {
//---------以下读入按键、消抖、等待按键释放
P1 = 0xf0;
Key_Temp1 = Keyscan(); //先读入按键
if(Key_Temp1 != 16) { //如果有键按下
//Delay_1ms(10); //延时一下
Display(Key_Value); //可用显示代替延时
Key_Temp2 = Keyscan(); //再读一次按键
if (Key_Temp1 == Key_Temp2) {//必须是两次相等
Key_Value = Key_Temp1; //才保存下来,这就是消除抖动
while(Keyscan() < 16) //等待按键释放
Display(Key_Value); //等待期间显示键值
//---------以下是对按键的处理
Display(Key_Value); //显示键值
} }
Display(Key_Value); //没有按键按下,也显示键值
}
}
程序分析:
程序中可分为3个子函数你和一个主函数,其中子函数void Delay_1ms(uint x)功能是延迟秒,x为一个整形变量,控制外层循环次数,由于晶振是12MHz那个内层循环循环一次为1/120ms,因此内层循环变量必须是小于120,
子函数uchar Keyscan(void)功能是键盘扫描,在P1高四位分别输出一个低电平,低四位输出一个高电平,即高四位为输出,第四位为输入,当接通时输入输出均为低电平,从而实现键盘输入的功能。
void Display(uchar k)函数的功能是将按下的键值输出到七段数码管,原理是将对输入对的键值(0-15)除以10,若键值不小于10,那么十位则为一,之后对键值取余,输出个位数字。
主函数对以上三个子函数进行调用,在初始化(初始值为16)后,限进行消除抖动,之后将输入的键值输出。
仿真效果
初始状态
键值为8
实验效果
初始状态
键值为01
键值为10
键值为15
问题分析
本次试验我们组存在一些问题,首先是在键盘的输入端口,将排线接错,P1.0端口与P1.1端口位置接错,致使输入不正常;其次是排查问题的时候忽略了按键的原因,键值为6的按键损坏,致使键盘无法输入;最后显示的数字不正常,其原因是在共阳极改共阴极的时,没有将多余的线路拆除,从而影响输出。
总结经验,在焊接时首先确定器件的好坏,之后更应该注意线路连接及布线的正确性,一致达到实验要求的目的。