最近做了一个门禁卡小玩意,用到了4X4矩阵按键,在这里也单独的记录一下。
矩阵按键图
思路:
矩阵按键读取键值写法多样,有一行一行的检测,也有是全部行检测,我这里是全部去扫。
先扫描4列是否有按下,有 再切换 扫描所有行。
第一步:先让行拉低(输出模式),去检测列(输入模式 拉高)
如果检测到有
第二步:让列拉低(输出模式), 去检测行(输入模式 拉高)
第三步:这样就可以获取到哪按键按下了。
#include "matrix_key.h"
#include "usart.h"
uint8_t key_flag;
/*4X4矩阵按键的表盘设置*/
const uint8_t matrix_key_tab[4][4] =
{
'1', '2', '3', 'A',
'4', '5', '6', 'B',
'7', '8', '9', 'C',
'*', '0', '#', 'D',
};
/***********************************************************************
描述: 按键 列 设置输入模式(前4个)
************************************************************************/
void key_set_list_input_mode(void)
{
GPIO_InitTypeDef KEY_InitStruction;
RCC_APB2PeriphClockCmd(KEY_RCC, ENABLE);
//列引脚
KEY_InitStruction.GPIO_Pin = KEY5_PIN | KEY6_PIN | KEY7_PIN | KEY8_PIN; //引脚
KEY_InitStruction.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(KEY_PORT, &KEY_InitStruction);
}
/***********************************************************************
描述: 按键 列 设置输出模式
************************************************************************/
void key_set_list_output_mode(void)
{
GPIO_InitTypeDef KEY_InitStruction;
RCC_APB2PeriphClockCmd(KEY_RCC, ENABLE);
//列引脚
KEY_InitStruction.GPIO_Pin = KEY5_PIN | KEY6_PIN | KEY7_PIN | KEY8_PIN; //引脚
KEY_InitStruction.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
KEY_InitStruction.GPIO_Speed = GPIO_Speed_50MHz; //速率
GPIO_Init(KEY_PORT, &KEY_InitStruction);
}
/***********************************************************************
描述: 按键 行 设置输入模式
************************************************************************/
void key_set_row_input_mode(void)
{
GPIO_InitTypeDef KEY_InitStruction;
RCC_APB2PeriphClockCmd(KEY_RCC, ENABLE);
//列引脚
KEY_InitStruction.GPIO_Pin = KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN; //引脚
KEY_InitStruction.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(KEY_PORT, &KEY_InitStruction);
}
/***********************************************************************
描述: 按键 行 设置输出模式
************************************************************************/
void key_set_row_output_mode(void)
{
GPIO_InitTypeDef KEY_InitStruction;
RCC_APB2PeriphClockCmd(KEY_RCC, ENABLE);
//列引脚
KEY_InitStruction.GPIO_Pin = KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN; //引脚
KEY_InitStruction.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
KEY_InitStruction.GPIO_Speed = GPIO_Speed_50MHz; //速率
GPIO_Init(KEY_PORT, &KEY_InitStruction);
}
/***********************************************************************
描述: 按键初始化函数
************************************************************************/
void matrix_key_init(void)
{
ROW_OUT_MODE; //行设置输出模式
LIST_INT_MODE; //列设置输入模式
}
/***********************************************************************
描述: 获取键值 函数
返回: 返回表盘对应键值
************************************************************************/
uint8_t matrix_key_scanf(void)
{
static uint8_t key_status;
uint8_t R,L;
uint8_t key_temp;
//检测列 所以我们让行拉低 列拉高
LIST_INT_MODE; LIST_SET_HIGH;
ROW_OUT_MODE; ROW_SET_LOW;
key_temp = ~GPIO_ReadInputData(KEY_PORT) & 0XF0;
if(key_temp == 0) {key_status = 0; return 0;}
//第一次检测到
if(key_status == 0)
{
key_status = 1;
return 0;
}
//第二次检测到
else if(key_status == 1)
{
key_status = 2;
//读取列
switch(key_temp)
{
case 0x10: L = 0; break;
case 0x20: L = 1; break;
case 0x40: L = 2; break;
case 0x80: L = 3; break;
default: return 0;
}
//快速转换模式
//再检测行是否有按键按下 所以先让列拉低 行拉高
LIST_OUT_MODE; LIST_SET_LOW; //PA4 ~ PA7
ROW_INT_MODE; ROW_SET_HIGH; //PA0 ~ PA3
key_temp = ~GPIO_ReadInputData(KEY_PORT) & 0X0F;
//读取行
switch(key_temp)
{
case 0x01: R = 0; break;
case 0x02: R = 1; break;
case 0x04: R = 2; break;
case 0x08: R = 3; break;
default: return 0;
}
return matrix_key_tab[R][L];;
}
//证明没松开按键
else if(key_status == 2)
{
return 0;
}
key_status = 0;
return 0;
}
/***********************************************************************
描述: 矩阵键盘处理 函数
************************************************************************/
void matrix_key_process(void)
{
uint8_t key_val;
if(key_flag)
{
key_flag = 0;
key_val = matrix_key_scanf(); //获取键值
if(key_val == 0) return;
printf("KEY:%c\r\n",key_val);
}
}
#ifndef __MATRIX_KEY_H
#define __MATRIX_KEY_H
#include "stm32f10x.h"
#define KEY_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY_PORT GPIOA //端口
#define KEY1_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY1_PORT GPIOA //端口
#define KEY1_PIN GPIO_Pin_0 //引脚
#define KEY2_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY2_PORT GPIOA //端口
#define KEY2_PIN GPIO_Pin_1 //引脚
#define KEY3_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY3_PORT GPIOA //端口
#define KEY3_PIN GPIO_Pin_2 //引脚
#define KEY4_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY4_PORT GPIOA //端口
#define KEY4_PIN GPIO_Pin_3 //引脚
#define KEY5_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY5_PORT GPIOA //端口
#define KEY5_PIN GPIO_Pin_4 //引脚
#define KEY6_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY6_PORT GPIOA //端口
#define KEY6_PIN GPIO_Pin_5 //引脚
#define KEY7_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY7_PORT GPIOA //端口
#define KEY7_PIN GPIO_Pin_6 //引脚
#define KEY8_RCC RCC_APB2Periph_GPIOA //时钟
#define KEY8_PORT GPIOA //端口
#define KEY8_PIN GPIO_Pin_7 //引脚
#define ROW_INT_MODE key_set_row_input_mode()
#define ROW_OUT_MODE key_set_row_output_mode()
#define LIST_INT_MODE key_set_list_input_mode()
#define LIST_OUT_MODE key_set_list_output_mode()
#define LIST_SET_HIGH {GPIO_SetBits(KEY_PORT,KEY5_PIN);GPIO_SetBits(KEY_PORT,KEY6_PIN);GPIO_SetBits(KEY_PORT,KEY7_PIN);GPIO_SetBits(KEY_PORT,KEY8_PIN);}
#define LIST_SET_LOW {GPIO_ResetBits(KEY_PORT,KEY5_PIN);GPIO_ResetBits(KEY_PORT,KEY6_PIN);GPIO_ResetBits(KEY_PORT,KEY7_PIN);GPIO_ResetBits(KEY_PORT,KEY8_PIN);}
#define ROW_SET_HIGH {GPIO_SetBits(KEY_PORT,KEY1_PIN);GPIO_SetBits(KEY_PORT,KEY2_PIN);GPIO_SetBits(KEY_PORT,KEY3_PIN);GPIO_SetBits(KEY_PORT,KEY4_PIN);}
#define ROW_SET_LOW {GPIO_ResetBits(KEY_PORT,KEY1_PIN);GPIO_ResetBits(KEY_PORT,KEY2_PIN);GPIO_ResetBits(KEY_PORT,KEY3_PIN);GPIO_ResetBits(KEY_PORT,KEY4_PIN);}
extern const uint8_t key_tab[4][5];
extern uint8_t key_flag;
void key_set_list_input_mode(void); //按键 列 设置输入模式
void key_set_list_output_mode(void); //按键 列 设置输出模式
void key_set_row_input_mode(void); //按键 行 设置输入模式
void key_set_row_output_mode(void); //按键 行 设置输出模式
void matrix_key_init(void); //按键初始化
uint8_t matrix_key_scanf(void); //获取按键键值
void matrix_key_process(void);
#endif
#include "stm32f10x.h"
#include "timer.h"
#include "matrix_key.h"
#include "usart.h"
/*
接线:
4X4矩阵按键
行: PA0 ~ PA3
列: PA4 ~ PA7
*/
int main()
{
usart1_init(115200); //串口1初始化 用于输出键值
matrix_key_init(); //矩阵按键初始化
timer3_init(); //定时器3初始化 用于去检测按键
while(1)
{
matrix_key_process(); //矩阵按键检测和处理
}
}
如果我哪里写的有问题,或者不好,请大家多多指教
#整个工程代码。
printf("+meQ:844797079\n")
如果觉得这篇文章对你有用。欢迎大家点赞、评论哈哈
继续加油!!!