4x4矩形键盘接口与编程

合集下载

4x4键盘程序

4x4键盘程序
数码管采用共阴数码管,接p1口,接口顺序如下:
a--p1.0
b--p1.1
c--p1.2
d--p1.3
e--p1.4
f--p1.5
g--p1.6
cp--p1.7
#include<reg51.h>
#defineucharunsigned char
#defineuintunsignedint
//sbitkey1=P3^4;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb: num=9;break;
case 0xdb: num=10;break;
case 0xbb: num=11;break;
case 0x7b: num=12;break;
default: break;
while(temp!=0xf0)
{
delay(5);//消抖
temp=P3;//再次读P3口的数据
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7: num=13;break;
case 0xd7: num=14;break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
P1=table[num-1];
P3=0xf7;//将第四行电平拉低
temp=P3;//扫面P3口的数据,送给temp

4X4矩阵按键原理和代码解析(老伙计)

4X4矩阵按键原理和代码解析(老伙计)

4X4 矩阵按键原理和代码解析目录1 键盘概述 (1)2 矩阵按键工作原理 (2)3、4X4 矩阵按键代码解析 (2)1 键盘概述键盘分编码键盘和非编码键盘。

键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。

而靠软件编程来识别的称为非编码键盘。

在一般嵌入式应用中,用的最多的是非编码键盘,也有用到编码键盘的。

非编码键盘又分为独立键盘和行列式(又称为矩阵式)键盘。

所谓独立式键盘,即嵌入式CPU (或称MCU)的一个GPIO 口对应一个按键输入,这个输入值的高低状态就是键值。

矩阵键盘用于采集键值的GPIO 是复用的,一般分为行和列采集,例如4*4 矩阵键盘就只需要行列各4 个按键就可以了,矩阵键盘的控制较独立键盘要复杂得多,本实验未涉及,所以对其原理不做详细介绍。

独立按键一般有2 组管脚,虽然市面上我们常常看到有4个管脚的按键,但它们一般是两两导通的,这2 组管脚在按键未被按下时是断开的,在按键被按下时则是导通的。

基于此原理,我们一般会把按键的一个管脚接地,另一个管脚上拉到VCC,并且也连接到GPIO。

这样,在按键未被按下时,GPIO 的连接状态为上拉到VCC,则键值为1;按键被按下时,GPIO虽然还是上拉到VCC,但同时被导通的另一个管脚拉到地了,所以它的键值实际上是0。

我们的开发板上有一组4*4 矩阵键盘。

通过P12 的PIN1-2 短接时,其实S1/S2/S3/S4 可以作为独立按键使用,它的一端接地,另一端在上拉的同时连接到FPGA 的I/O 口。

当I/O 口的电平为高(1)时,说明按键没有被按下,当I/O口的电平为低(0)时,说明按键被按下了。

我们不再只局限于独立按键这么low 的应用了,这里我们将要把所有16 个按键都使用起来,实现我们真正的矩阵按键功能。

要做矩阵按键,那么大家首先要确认把自己的SF-CY4 开发板上插座P12 的PIN2-3用跳线帽短接。

实验四4×4键盘输入

实验四4×4键盘输入

实验四: 4 × 4键盘输入实验一、实验目的:1.学习非编码键盘的工作原理和键盘的扫描方式。

2.学习键盘的去抖方法和键盘应用程序的设计。

二、实验原理:键盘是单片机应用系统接受用户命令的重要方式。

单片机应用系统一般采用非编码键4*4矩阵盘,需要由软件根据键扫描得到的信息产生键值编码,以识别不同的键。

本板采用键盘,行信号分别为P1.0-P1.3 ,列信号分别为P1.4-P1.7 。

具体电路连接见下图对于键的识别一般采用逐行(列)扫描查询法,判断键盘有无键按下,由单片机I/O口向键盘送全扫描字,然后读入列线状态来判断。

程序及流程图:ORG 0000HAJMP MAINORG 0000HAJMP MAINORG 0030HMAIN:MOV P2,#0F7HMOV P1,#0F0HMOV R7,#100DJNZ R7,$MOV A,P1ANL A,#0F0HXRL A,#0F0HJZ MAINLCALL D10MSMOV A,#00HMOV R0,AMOV R1,AMOV R2,#0FEH SKEY0:MOV A,R2MOVP1,AMOVR7,#10DJNZ R7,$MOVA,P1ANLA,#0F0HXRLA,#0F0HJNZ LKEYINC R0MOVA,R2RL AMOVR2,AMOVA,R0CJNE A,#04H,SKEY0AJMP MAIN LKEY:JNB ACC,4,NEXT1MOVA,#00HMOVR1,AAJMP DKEYNEXT1:JNB ACC.5,NEXT2MOVA,#01HMOVR1,AAJMP DKEYNEXT2:JNB ACC.6,NEXT3MOVA,#02HMOVR1,AAJMP DKEYNEXT3:JNB ACC.7,MAINMOVA,#03HMOVR1,AAJMP DKEY DKEY:MOV A,R0MOVB,#04HMULABADDA,R1AJMP SQRSQR:MOVDPTR,#TABMOVC A,@A+DPTRMOVP0,AAJMP MAINTAB:DB0C0H,0F9H,0A4H,0B0H,99H, 92H, 82H, 0F8H DB 80H, 90H, 88H, 83H, 0C6H,0A1H,86H, 8EH D10MS:MOV R6,#10L1:MOV R5,#248DJNZ R5,$DJNZ R6,L1RETEND流程图:结束三、思考题:总结 FPGA是如何识别按键的?与单片机读取键值有何不同?答:FPGA的所有 I/O 控制块允许每个 I/O 引脚单独配置为输入口 , 不过这种配置是系统自动完成的。

单片机实现4X4矩阵键盘控制项目PPT课件

单片机实现4X4矩阵键盘控制项目PPT课件

-
5
• 在矩阵按键处理过程中,一旦检测到有按 键闭合与确认按键已经稳定闭合期间,通 过调用10-20ms延时子程序避开按键抖动问 题。由于按键是机械器件,按下或者松开 时有固定的机械抖动,抖动图如图所示。
-
6
• 按键去抖分为硬件去抖和软件去抖,硬件去抖最简单的是 按键两端并联电容,容量根据实验而定。软件去抖使用方 便不增加硬件成本,容易调试,所以现在处理按键抖动问 题大部分选择软件去抖。软件去抖操作步骤如下:
-
10
13.4 项目软件程序设计
• 矩阵键盘行线P20~P23为输出线,列线 P24~P27为输入线。单片机将行线(P20~P23) 全部输出低电平,此时读入列线数据,若列线 全为高电平则没有键按下,当列线有出现低电 平时调用延时程序以此来去除按键抖动。延时 完成后再判断是否有低电平,如果此时读入列 线数据还是有低电平,则说明确实有键按下, 再来进一步确定键值。
51单片机
VC C P0. 0 P0. 1 P0. 2 P0. 3 P0. 4 P0. 5 P0. 6 P0. 7 EA/VPP PROG/ ALE PSEN A15/P2. 7 A14/P2. 6 A13/P2. 5 A12/P2. 4 A11/P2. 3 A10/P2. 2 A9/P2. 1 A8/P2. 0

case 0xdd:P0=table[5];break; //显示按键码“5”

case 0xbd:P0=table[6];break; //显示按键码“6”

case 0x7d:P0=table[7];break; //显示按键码“7”

case 0xeb:P0=table[8];break; //显示按键码“8”

4×4矩阵按键

4×4矩阵按键
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7:num=13;
break;
case 0xd7:num=14;
break;
case 0xb7:num=15;
DQ = 1; //释放总线
dat>>=1; //移入下一位
}
}
void temperature_read(void)
{
//unsigned int t;
ds18b20_init();
if(presence==0) //器件应答
{
ds18b20_write(0xCC); //跳过读序号列号的操作
ds18b20_write(0x44);//启动温度转换
lcden=1; //开使能
delayms(5); //读取数据
lcden=0;//关闭使能
}
//**********LCD初始化函数开始*********
void lcd_initialize()
{
lcden=0;
write_com(0x38); //设置16x2显示,5x7点阵显示,8位数据接口
{
unsigned char i=0,dat=0;
for (i=8;i>0;i--)
{
DQ = 0; //给脉冲信号
dat>>=1; //移入一位
DQ = 1; //释放总线
if(DQ)
dat|=0x80; //写入1

STM32-矩阵键盘程序4×4课件.doc

STM32-矩阵键盘程序4×4课件.doc

/*--------------------------------------------------------------------------------------* 矩阵键盘驱动* 文件: keyboard.c* 编写人:LiuHui* 描述:扫描4x4 矩阵键盘输入,并返回键值* 适用范围:驱动采用ST3.5 库编写,适用于STM32F10x 系列单片机* 所用引脚:PA0-PA7* 编写时间:2014 年5 月20 日--------------------------------------------------------------------------------------*/#include "stm32f10x.h"#include "keyboard.h"#include "dealy.h"/*-------------------------------- 矩阵键盘初始化----------------------------------------* 功能:初始化stm32 单片机GPIO //PA0-PA7* 参数传递:* 输入:无* 返回值:无--------------------------------------------------------------------------------------*/void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);}/*------------------------------ 矩阵键盘扫描--------------------------------------------* 功能:扫描矩阵键盘,并返回键值* 参数:* 输入:无* 返回:有键按下返回该键值* 无键按下时则返回0--------------------------------------------------------------------------------------*/u8 Read_KeyValue(void){u8 KeyValue=0;if((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f){Delay_ms(10);if((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f){GPIO_SetBits(GPIOA, GPIO_Pin_0);GPIO_ResetBits(GPIOA, GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x11: KeyValue = 1; break;case 0x21: KeyValue = 5; break;case 0x41: KeyValue = 9; break;case 0x81: KeyValue = 13;break;}GPIO_SetBits(GPIOA, GPIO_Pin_1);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x12: KeyValue = 2; break;case 0x22: KeyValue = 6; break;case 0x42: KeyValue = 10;break;case 0x82: KeyValue = 14;break;}GPIO_SetBits(GPIOA, GPIO_Pin_2);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x14: KeyValue = 3; break;case 0x24: KeyValue = 7; break;case 0x44: KeyValue = 11;break;case 0x84: KeyValue = 15;break;}GPIO_SetBits(GPIOA, GPIO_Pin_3);GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);switch(GPIO_ReadInputData(GPIOA)&0xff){case 0x18: KeyValue = 4; break;case 0x28: KeyValue = 8; break;case 0x48: KeyValue = 12;break;case 0x88: KeyValue = 16;break;}GPIO_SetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3); GPIO_ResetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 |GPIO_Pin_7);while((GPIO_ReadInputData(GPIOA)&0xff)!=0x0f);return KeyValue;}}return 0;}/*--------------------------------THE END--------------------------------------------*//*--------------------------------------------------------------------------------------* 矩阵键盘驱动* 文件: keyboard.h* 编写人:LiuHui* 描述:扫描4x4 矩阵键盘输入,并返回键值* 适用范围:驱动为ST3.5 库编写,适用于STM32F10x 系列单片机* 所用引脚:PA0-PA7* 编写时间:2013 年11 月22 日* 版本: 1.0--------------------------------------------------------------------------------------*/#ifndef __KEYBOARD_H#define __KEYBOARD_Hvoid KeyBoard_Init(void);u8 Read_KeyValue(void);#endif/*----------------------------------THE END------------------------------------------*#include "stm32f10x.h"void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);}//3?ê?? ˉPA,PBvoid Delay_ms(int time){int i=0;while(time--){i=12000;while(i--);}}u8 Read_KeyValue(void){u8 KeyValue=1;if((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f){Delay_ms(10);if((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f){GPIO_SetBits(GPIOB, GPIO_Pin_3);GPIO_ResetBits(GPIOB, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6); switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x11: KeyValue = 7; break;case 0x21: KeyValue = 4; break;case 0x41: KeyValue = 1; break;case 0x81: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_4);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6); switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x12: KeyValue = 8; break;case 0x22: KeyValue = 5; break;case 0x42: KeyValue = 2; break;case 0x82: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6);switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x14: KeyValue = 9; break;case 0x24: KeyValue = 6; break;case 0x44: KeyValue = 3; break;case 0x84: KeyValue = 0; break;}GPIO_SetBits(GPIOB, GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5);switch(GPIO_ReadInputData(GPIOB)&0xff){case 0x18: KeyValue = 0; break;case 0x28: KeyValue = 0; break;case 0x48: KeyValue = 0;break;case 0x88: KeyValue = 0;break;}GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6); GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);//while((GPIO_ReadInputData(GPIOB)&0xff)!=0x0f);return KeyValue;}}return 0;}uint16_t table[]={0xEB,0x28,0xB3,0xBA,0x78,0xDA,0xDB,0xA8,0xFB,0xFA};int main(){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);KeyBoard_Init();int keyvalue=Read_KeyValue();GPIO_Write(GPIOA, table[keyvalue]);/*while(1){int i;for(i=0;i<10;i++){GPIO_Write(GPIOA, table[i]);Delay_ms(500);}}*//*u8 keyvalue;for(int i=0;;i++){KeyBoard_Init();keyvalue=Read_KeyValue();GPIO_Write(GPIOA,table[keyvalue]);Delay_ms(500);}*/}#include "stm32f10x.h"void KeyBoard_Init(void){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6);GPIO_ResetBits(GPIOB, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);}void Delay_ms(int time){int i=0;while(time--){i=12000;while(i--);}}u8 Read_KeyValue(void){if((GPIO_ReadInputData(GPIOB)&0xff)!=0x73)// 在这个程序下为什么无论是GPIO_ReadInputData(GPIOB)&0xff)!=0x73 还是GPIO_ReadInputData(GPIOB)&0xff)==0x73 都能往下运行,而在屏蔽Delay_ms(10) 后则只能运行一种,是因为这个Delay_ms(10) 对if 里的判断有影响吗?{Delay_ms(10);GPIO_Write(GPIOA,0x33);}return 0;}int main(){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);KeyBoard_Init();Read_KeyValue();}。

4X4矩阵键盘+1602——51单片机的Proteus实验

4X4矩阵键盘+1602——51单片机的Proteus实验

4X4矩阵键盘+1602——51单片机的Proteus实验本文转载自小波电子工作室。

C语言源代码//======================================================依次可以从键盘输入0-f,在1602LCD上显示出来(此程序在所买开发板上验证通过)//======================================================//******** 小波电子工作室All rights reserved******//******** 个人主页:/niejinbo **//******** 文件名:lcd_key.1.c ************//******** 功能概要:4*4矩阵键盘扫描***********//******** MCU: STC89C52 晶振:11.0592Mhz **********//******** 设计者:聂金波************//******** 完成日期:2008-07-14 ************//******** 当前版本:0714.1 ************//******** 改进说明:暂无************//******** 补充说明: 从键盘输入0-F,在LCD上显示出来//*********头文件区*******************#include<reg52.h>#include<math.h>#include<absacc.h>#define uchar unsigned char#define uint unsigned int//*********定义变量区*******************sbit dula=P2^6; //关闭数码管显示之用sbit wela=P2^7;sbit lcden=P3^4; //LCD使能信号sbit lcdrs=P3^5; //LCD数据/命令选择信号uchar tab_key[50];uchar code tab[]="0123456789abcdef";uchar n=0,temp,key;//*********函数声明区********************void lcd_disp(); //LCD显示函数void lcd_init(); //LCD初始化函数void write_com(uchar); //写命令函数void write_data(uchar); //写数据函数void delay(uint); //延迟函数void key_scan(); //键盘扫描函数void key_manage1(); //键盘功能分配函数void key_manage2();void key_manage3();void key_manage4();void key_manage5();void key_manage6();void key_manage7();void key_manage8();void key_manage9();void key_manage10();void key_manage11();void key_manage12();void key_manage13();void key_manage14();void key_manage15();void key_manage16();//**********主函数开始**********void main(){lcd_init();write_com(1);while(1){key_scan();lcd_disp();}}//**********LCD显示函数开始***********void lcd_disp(){uchar a,i=0;write_com(0x80);for(i=0;i<n;i++){a=tab_key[i];write_data(tab[a]);}}//**********LCD初始化函数开始*********void lcd_init(){dula=0;wela=0; // 关闭数码管显示lcden=0;write_com(0x38); //设置显示模式:16X2,5X7,8位数据接口write_com(0x0c); //开显示,显示光标,光标闪烁write_com(0x06); //读写一个字符后,地址指针及光标加一,且光标加一整屏显示不移动write_com(0x80); //设置光标指针}//**********写命令函数开始************void write_com(uchar com){lcdrs=0; //低电平写命令P0=com; //写入命令delay(3); //延时约3mslcden=1; //LCD使能端置高电平delay(5); //延时约5mslcden=0; //LCD使能端拉低电平}//**********写数据函数开始************void write_data(uchar dat){lcdrs=1; //低电平写数据P0=dat; //写入命令delay(3); //延时约3mslcden=1; //LCD使能端置高电平delay(5); //延时约5mslcden=0; //LCD使能端拉低电平}//**********键盘扫描函数开始**** void key_scan(){//**********扫描第一行*********P3=0xfe;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xee:key_manage1();break;case 0xde:key_manage2();break;case 0xbe:key_manage3();break;case 0x7e:key_manage4();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第二行*********P3=0xfd;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xed:key_manage5();break;case 0xdd:key_manage6();break;case 0xbd:key_manage7();break;case 0x7d:key_manage8();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第三行********* P3=0xfb;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xeb:key_manage9();break;case 0xdb:key_manage10();break;case 0xbb:key_manage11();break;case 0x7b:key_manage12();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}//**********扫描第四行********* P3=0xf7;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(100);if(temp!=0xf0){temp=P3;switch(temp){case 0xe7:key_manage13();break;case 0xd7:key_manage14();break;case 0xb7:key_manage15();break;case 0x77:key_manage16();break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}}}}//*********延时函数开始************** void delay(uint k){uint i,j;for(i=k;i>0;i--)for(j=50;j>0;j--);}//******键盘功能分配函数群开始********// 键盘功能示意图// 设计者:聂金波//** 1 ** 2 ** 3 ** 4 **//** 5 ** 6 ** 7 ** 8 **//** 9 ** 0 ** s ** c **//** M1** M2** M3** M4**void key_manage1(){tab_key[n]=0;n++;}void key_manage2(){tab_key[n]=1;n++;}void key_manage3(){tab_key[n]=2;n++;}void key_manage4() {tab_key[n]=3;n++;}void key_manage5() {tab_key[n]=4;n++;}void key_manage6() {tab_key[n]=5;n++;}void key_manage7(){tab_key[n]=6;n++;}void key_manage8(){tab_key[n]=7;n++;}void key_manage9() {tab_key[n]=8;n++;}void key_manage10(){tab_key[n]=9;n++;}void key_manage11() {tab_key[n]=10;n++;}void key_manage12(){tab_key[n]=11;n++;}void key_manage13(){tab_key[n]=12;n++;}void key_manage14(){tab_key[n]=13;n++;}void key_manage15(){tab_key[n]=14;n++;}void key_manage16(){tab_key[n]=15;n++;}Proteus仿真图依次从键盘输入:abcd 277817639 (本人QQ号)4X4矩阵键盘-Proteus截图。

4乘4矩阵式键盘使用

4乘4矩阵式键盘使用

4乘4矩阵式键盘在单片机中的应用--C语言下图为4*4键盘的结果图,用单片机的P1口接4×4矩阵键盘,接法如图所示,用数码管显示按键的值,按下键S1,数码管显示0,按下S2,数码管显示1,按下S16,显示F。

先看程序代码:#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar code table[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0 x71};//八段数码管对应0—F值。

void Delay_1ms(uint i)//1ms延时{uchar x, j;for(j=0;j<i;j++)for(x=0;x<=148;x++);}void delay()//消除按键抖动延时{int i,j;for(i=0; i<=10; i++)for(j=0; j<=2; j++);}uchar Keyscan(void){uchar i,j, temp, Buffer[4] = {0xfe, 0xfd, 0xfb, 0xf7};for(j=0; j<4; j++){P1 = Buffer[j];delay();temp = 0x10;for(i=0; i<4; i++){if(!(P1 & temp)){return (i+j*4);}temp <<= 1;}}}voidMain(void){uchar Key_Value;//读出的键值while(1){P1 = 0xf0;if(P1 != 0xf0){Delay_1ms(15);//按键消抖if(P1 != 0xf0){Key_Value = Keyscan();}}P0 = table[Key_Value];//P0口输出数据到数码管}}代码分析:程序从Main开始执行,Key_Value用来存放Keyscan();的返回值,Key_Value 为1,则数码管会显示1。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机教程第二十五课:键盘接口与编程键盘是由若干按键组成的开关矩阵,它是微型计算机最常用的输入设备,用户可以通过键盘向计算机输入指令、地址和数据。

一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。

按键开关的抖动问题组成键盘的按键有触点式和非触点式两种,单片机中应用的一般是由机械触点构成的。

在下图中,当开图1图2 关S 未被按下时,P1。

0输入为高电平,S 闭合后,P1。

0输入为低电平。

由于按键是机械触点,当机械触点断开、闭合时,会有抖动动,P1。

0输入端的波形如图2所示。

这种抖动对于人来说是感觉不到的,但对计算机来说,则是完全可以感应到的,因为计算机处理的速度是在微秒级,而机械抖动的时间至少是毫秒级,对计算机而言,这已是一个“漫长”的时间了。

前面我们讲到中断时曾有个问题,就是说按键有时灵,有时不灵,其实就是这个原因,你只按了一次按键,可是计算机却已执行了多次中断的过程,如果执行的次数正好是奇数次,那么结果正如你所料,如果执行的次数是偶数次,那就不对了。

为使CPU 能正确地读出P1口的状态,对每一次按键只作一次响应,就必须考虑如何去除抖动,常用的去抖动的方法有两种:硬件方法和软件方法。

单片机中常用软件法,因此,对于硬件方法我们不介绍。

软件法其实很简单,就是在单片机获得P1。

0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P1。

0口,如果仍为低,说明S1的确按下了,这实际上是避开了按键按下时的抖动时间。

而在检测到按键释放后(P1。

0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。

不过一般情况下,我们通常不对按键释放的后沿进行处理,实践证明,也能满足一定的要求。

当然,实际应用中,对按键的要求也是千差万别,要根据不同的需要来编制处理程序,但以上是消除键抖动的原则。

键盘与单片机的连接图3 图41、通过1/0口连接。

将每个按键的一端接到单片机的I/O 口,另一端接地,这是最简单的方法,如图3所示是实验板上按键的接法,四个按键分别接到P3.2 、P3.3、P3.4和P3.5。

对于这种键各程序可以采用不断查询的方法,功能就是:检测是否有键闭合,如有键闭合,则去除键抖动,判断键号并转入相应的键处理。

下面给出一个例程。

其功能很简单,四个键定义如下:P3.2:开始,按此键则灯开始流动(由上而下)P3.3:停止,按此键则停止流动,所有灯为暗P3.4:上,按此键则灯由上向下流动P3.5:下,按此键则灯由下向上流动UpDown EQU 00H ;上下行标志StartEnd EQU 01H ;起动及停止标志LAMPCODE EQU 21H ;存放流动的数据代码ORG 0000HAJMP MAINORG 30HMAIN:MOV SP,#5FHMOV P1,#0FFHCLR UpDown ;启动时处于向上的状态CLR StartEnd ;启动时处于停止状态MOV LAMPCODE,#0FEH ;单灯流动的代码LOOP:ACALL KEY ;调用键盘程序JNB F0,LNEXT ;如果无键按下,则继续ACALL KEYPROC ;否则调用键盘处理程序LNEXT:ACALL LAMP ;调用灯显示程序AJMP LOOP ;反复循环,主程序到此结束DELAY:MOV R7,#100D1: MOV R6,#100DJNZ R6,$DJNZ R7,D1RET;----------------------------------------延时程序,键盘处理中调用KEYPROC:MOV A,B ;从B寄存器中获取键值JB ACC.2,KeyStart ;分析键的代码,某位被按下,则该位为1(因为在键盘程序中已取反)JB ACC.3,KeyOverJB ACC.4,KeyUpJB ACC.5,KeyDownAJMP KEY_RETKeyStart:SETB StartEnd ;第一个键按下后的处理AJMP KEY_RETKeyOver:CLR StartEnd ;第二个键按下后的处理AJMP KEY_RETKeyUp: SETB UpDown ;第三个键按下后的处理AJMP KEY_RETKeyDown:CLR UpDown ;第四个键按下后的处理KEY_RET:RETKEY:CLR F0 ;清F0,表示无键按下。

ORL P3,#00111100B ;将P3口的接有键的四位置1MOV A,P3 ;取P3的值ORL A,#11000011B ;将其余4位置1CPL A ;取反JZ K_RET ;如果为0则一定无键按下ACALL DELAY ;否则延时去键抖ORL P3,#00111100BMOV A,P3ORL A,#11000011BCPL AJZ K_RETMOV B,A ;确实有键按下,将键值存入B中SETB F0 ;设置有键按下的标志K_RET:ORL P3,#00111100B ;此处循环等待键的释放MOV A,P3ORL A,#11000011BCPL AJZ K_RET1 ;直到读取的数据取反后为0说明键释放了,才从键盘处理程序中返回AJMP K_RETK_RET1:RETD500MS: ;流水灯的延迟时间PUSH PSWSETB RS0MOV R7,#200D51: MOV R6,#250D52: NOPNOPNOPNOPDJNZ R6,D52DJNZ R7,D51POP PSWRETLAMP:JB StartEnd,LampStart ;如果StartEnd=1,则启动MOV P1,#0FFHAJMP LAMPRET ;否则关闭所有显示,返回LampStart:JB UpDown,LAMPUP ;如果UpDown=1,则向上流动MOV A,LAMPCODERL A ;实际就是左移位而已MOV LAMPCODE,AMOV P1,ALCALL D500MSAJMP LAMPRETLAMPUP:MOV A,LAMPCODERR A ;向下流动实际就是右移MOV LAMPCODE,AMOV P1,ALCALL D500MSLAMPRET:RETEND以上程序功能很简单,但它演示了一个键盘处理程序的基本思路,程序本身很简单,也不很实用,实际工作中还会有好多要考虑的因素,比如主循环每次都调用灯的循环程序,会造成按键反应“迟钝”,而如果一直按着键不放,则灯不会再流动,一直要到松开手为止,等等,大家可以仔细考虑一下这些问题,再想想有什么好的解决办法。

2、采用中断方式:如图4所示。

各个按键都接到一个与非上,当有任何一个按键按下时,都会使与门输出为低电平,从而引起单片机的中断,它的好处是不用在主程序中不断地循环查询,如果有键按下,单片机再去做相应的处理。

单片机教程第二十六课:矩阵式键盘接口技术及编程在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图1所示。

在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。

这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。

由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。

这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。

行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。

具体的识别及编程方法如下所述。

矩阵式键盘的按键识别方法确定矩阵式键盘上何键被按下介绍一种“行扫描法”。

行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,如上图所示键盘,介绍过程如下。

判断键盘中有无键按下将全部行线Y0-Y3置低电平,然后检测列线的状态。

只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。

若所有列线均为高电平,则键盘中无键按下。

判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭合键的过程。

其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。

在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。

若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

下面给出一个具体的例子:图仍如上所示。

8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。

列线P1.0-P1.3分别接有4个上拉电阻到正电源+5V,并把列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。

4根行线和4根列线形成16个相交点。

检测当前是否有键被按下。

检测的方法是P1.4-P1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键闭合。

去除键抖动。

当检测到有键按下后,延时一段时间再做下一步的检测判断。

若有键被按下,应识别出是哪一个键闭合。

方法是对键盘的行线进行扫描。

P1.4-P1.7按下述4种组合依次输出:P1.7 1 1 1 0P1.6 1 1 0 1P1.5 1 0 1 1P1.4 0 1 1 1在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。

由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值为了保证键每闭合一次CPU仅作一次处理,必须却除键释放时的抖动。

键盘扫描程序:从以上分析得到键盘扫描程序的流程图如图2所示。

程序如下SCAN: MOV P1,#0FHMOV A,P1ANL A,#0FHCJNE A,#0FH,NEXT1SJMP NEXT3NEXT1: ACALL D20MSMOV A,#0EFHNEXT2: MOV R1,AMOV P1,AMOV A,P1ANL A,#0FHCJNE A,#0FH,KCODE;MOV A,R1SETB CRLC AJC NEXT2NEXT3: MOV R0,#00HRETKCODE: MOV B,#0FBHNEXT4: RRC AINC BJC NEXT4MOV A,R1SWAP ANEXT5: RRC AINC BINC BINC BINC BJC NEXT5NEXT6: MOV A,P1ANL A,#0FHCJNE A,#0FH,NEXT6MOV R0,#0FFHRET键盘处理程序就作这么一个简单的介绍,实际上,键盘、显示处理是很复杂的,它往往占到一个应用程序的大部份代码,可见其重要性,但说到,这种复杂并不来自于单片机的本身,而是来自于操作者的习惯等等问题,因此,在编写键盘处理程序之前,最好先把它从逻辑上理清,然后用适当的算法表示出来,最后再去写代码,这样,才能快速有效地写好代码。

相关文档
最新文档