一、绪论
按键被广泛用于单片机控制,对于16个按键来说,假如还采用一个IO口控制一个按键的方式,那么单片机的IO口将会被占用的较多。所以在这里主要记录一下4*4矩阵键盘的实现方法。通过8个端口与单片机连接,4个IO口控制行,4个IO口控制列。
二、原理描述
这里我通过按行按列的方式确定每一次按下的按键具体是哪一个。
PA0-PA3控制行值,PA4-PA7控制列值
三、确定行值
1、将PA4-PA7配置为输出,PA0-PA3配置为输入
2、输出均置为下拉,即为0;输入均配置为上拉,即为1(有上拉电阻可以忽略配置模式)
3、当按下某个按键后,及该按键所连接的列置为0,例如按下S0,此时值为下图所示
四、确定列值
1、将PA0-PA3配置为输出,PA4-PA7配置为输入
2、输出均置为下拉,即为0;输入均配置为上拉,即为1
3、当按下某个按键后,及该按键所连接的列置为0,例如按下S0,此时值为下图所示
五、确定按键值
通过前面两步,0x70|0x08,可以确定此时S1的位置为:0x77
其余按键均可按此逻辑获得。
部分代码如下:
key.c
//确定行值
void Key_Init1(void){
RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_Level_2;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_Level_2;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
//确定列值
void Key_Init2(void){
RCC_AHBPeriphResetCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_Level_2;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_Level_2;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
//按键扫描
uint16_t Key_Scan(void){
uint16_t row,col,res;
Key_Init1();
col=GPIO_ReadInputData(GPIOA);
col=col&0x0f;
if(col!=0x0f)
{
delay10us(200);
col=GPIO_ReadInputData(GPIOA);
col=col&0x0f;
if(col!=0x0f)
{
col=GPIO_ReadInputData(GPIOA);
col=col&0x0f;//0x07
}
Key_Init2();
row=GPIO_ReadInputData(GPIOA);
row=row&0xf0;
if(row!=0xf0)
{
delay10us(200);
row=GPIO_ReadInputData(GPIOA);
row=row&0xf0;
if(row!=0xf0)
{
row=GPIO_ReadInputData(GPIOA);
row=row&0xf0;//0x70
}
res=row|col;
}
}
return res;
}
key.h
#ifndef _MYKEY_H_
#define _MYKEY_H_
#include "stdint.h"
void Key_Init1(void);
void Key_Init2(void);
uint16_t Key_Scan(void);
#endif
main.c,核心代码展示
while(1)
{
keyValue=Key_Scan();
switch(keyValue)
{
case 0x77://写上你的按键功能代码
break;
case 0x7b:break;
case 0x7d:break;
case 0x7e:break;
case 0xb7:break;
case 0xbb:break;
case 0xbd:break;
case 0xbe:break;
case 0xd7:break;
case 0xdb:break;
case 0xdd:break;
case 0xde:break;
case 0xe7:break;
case 0xeb:break;
case 0xed:break;
case 0xee:break;
default:
break;
}
}