基本介绍
最近做了一个门禁卡小玩意,用到了4X4矩阵按键,在这里也单独的记录一下。
矩阵按键图
思路:
矩阵按键读取键值写法多样,有一行一行的检测,也有是全部行检测,我这里是全部去扫。
先扫描4列是否有按下,有 再切换 扫描所有行。
第一步:先让行拉低(输出模式),去检测列(输入模式 拉高)
如果检测到有
第二步:让列拉低(输出模式), 去检测行(输入模式 拉高)
第三步:这样就可以获取到哪按键按下了。
代码
matrix_key.c
- #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);
- }
- }
复制代码
matrix_key.h
- #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
复制代码
main.c
- #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")
复制代码
————————————————
转载:皮卡丘吉尔
|