版权声明:如需转载请标注 https://blog.csdn.net/weixin_40973138/article/details/86607562
本文有关矩阵键盘的使用原理适用于所有微机控制器,同时也适用于所有规格的矩阵键盘。
key.h
/**
******************************************************************************
* @file bsp_key.h
* @author Waao
* @version V1.0.0
* @date 23-Jan-2019
* @brief This file contains some board support package's definition for the KEY.
*
******************************************************************************
* @attention
*
* None
*
******************************************************************************
*/
#ifndef __BSP_KEY_H_
#define __BSP_KEY_H_
#include <stm32f4xx.h>
#include <bsp_systick.h>
#include <bsp_usart.h>
// Column1, Column2, Column3, Column4
#define C1_PIN GPIO_Pin_2
#define C1_GPIO_PORT GPIOE
#define C1_GPIO_CLK RCC_AHB1Periph_GPIOE
#define C2_PIN GPIO_Pin_3
#define C2_GPIO_PORT GPIOE
#define C2_GPIO_CLK RCC_AHB1Periph_GPIOA
#define C3_PIN GPIO_Pin_4
#define C3_GPIO_PORT GPIOE
#define C3_GPIO_CLK RCC_AHB1Periph_GPIOA
#define C4_PIN GPIO_Pin_5
#define C4_GPIO_PORT GPIOE
#define C4_GPIO_CLK RCC_AHB1Periph_GPIOE
// Row1, Row2, Row3, Row4
#define R1_PIN GPIO_Pin_12
#define R1_GPIO_PORT GPIOB
#define R1_GPIO_CLK RCC_AHB1Periph_GPIOB
#define R2_PIN GPIO_Pin_13
#define R2_GPIO_PORT GPIOB
#define R2_GPIO_CLK RCC_AHB1Periph_GPIOB
#define R3_PIN GPIO_Pin_14
#define R3_GPIO_PORT GPIOB
#define R3_GPIO_CLK RCC_AHB1Periph_GPIOB
#define R4_PIN GPIO_Pin_15
#define R4_GPIO_PORT GPIOB
#define R4_GPIO_CLK RCC_AHB1Periph_GPIOB
// detect and output
#define DETECT_C1 GPIO_ReadInputDataBit(C1_GPIO_PORT, C1_PIN)
#define DETECT_C2 GPIO_ReadInputDataBit(C2_GPIO_PORT, C2_PIN)
#define DETECT_C3 GPIO_ReadInputDataBit(C3_GPIO_PORT, C3_PIN)
#define DETECT_C4 GPIO_ReadInputDataBit(C4_GPIO_PORT, C4_PIN)
#define DETECT_R1 GPIO_ReadInputDataBit(R1_GPIO_PORT, R1_PIN)
#define DETECT_R2 GPIO_ReadInputDataBit(R2_GPIO_PORT, R2_PIN)
#define DETECT_R3 GPIO_ReadInputDataBit(R3_GPIO_PORT, R3_PIN)
#define DETECT_R4 GPIO_ReadInputDataBit(R4_GPIO_PORT, R4_PIN)
// Keys
#define S1 0x77
#define S2 0xB7
#define S3 0xD7
#define S4 0xE7
#define S5 0x7B
#define S6 0xBB
#define S7 0xDB
#define S8 0xEB
#define S9 0x7D
#define S10 0xBD
#define S11 0xDD
#define S12 0xED
#define S13 0x7E
#define S14 0xBE
#define S15 0xDE
#define S16 0xEE
void GPIO_RCC_Config(void);
void ROCI_GPIO_Config(void);
void RICO_GPIO_Config(void);
void KEY_GPIO_ConfigAndDetect(void);
#endif
有关输入输出管脚的选择可以多试验几组,有的管脚即使你配置成上拉输入,当你松开按键之后依然不会返回高电平,我在此就因为这个问题被卡了一阵子
关于我的矩阵键盘检测的原理简明阐述如下:
- 首先设置为行输出低电平,列上拉输入(即无外部干扰时保持高电平);
- 检测到按键按下,此时通过检测列的电平情况从而得知哪一列有按键被按下;
- 然后确定有按键被按下后,设置为列输出低电平,行上拉输入;
- 通过检测行的电平情况从而得知哪一行有按键被按下;
- 最后通过“不平行的两条直线相交于一点”原理,推知具体被按下的按键。
key.c
/**
******************************************************************************
* @file bsp_key.c
* @author Waao
* @version V1.0.0
* @date 23-Jan-2019
* @brief This file contains some board support package's functions for the KEY.
*
******************************************************************************
* @attention
*
* None
*
******************************************************************************
*/
#include <bsp_key.h>
/**
* @brief Initialize the RCC of the 8 GPIO line.
* @param None
* @retval None
*/
void GPIO_RCC_Config(void)
{
RCC_AHB1PeriphClockCmd(C1_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(C2_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(C3_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(C4_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(R1_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(R2_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(R3_GPIO_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(R4_GPIO_CLK, ENABLE);
}
/**
* @brief Initialize the Row out Column in.
* @param None
* @retval None
*/
void ROCI_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_Structure;
//============ Column =============
GPIO_Structure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Structure.GPIO_OType = GPIO_OType_PP;
GPIO_Structure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Structure.GPIO_Pin = C1_PIN;
GPIO_Init(C1_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C2_PIN;
GPIO_Init(C2_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C3_PIN;
GPIO_Init(C3_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C4_PIN;
GPIO_Init(C4_GPIO_PORT, &GPIO_Structure);
//============== Row ===============
GPIO_Structure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Structure.GPIO_OType = GPIO_OType_PP;
GPIO_Structure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Structure.GPIO_Pin = R1_PIN;
GPIO_Init(R1_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R2_PIN;
GPIO_Init(R2_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R3_PIN;
GPIO_Init(R3_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R4_PIN;
GPIO_Init(R4_GPIO_PORT, &GPIO_Structure);
GPIO_ResetBits(R1_GPIO_PORT, R1_PIN);
GPIO_ResetBits(R2_GPIO_PORT, R2_PIN);
GPIO_ResetBits(R3_GPIO_PORT, R3_PIN);
GPIO_ResetBits(R4_GPIO_PORT, R4_PIN);
}
/**
* @brief Initialize the Row in Column out.
* @param None
* @retval None
*/
void RICO_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_Structure;
//============== Row ==================
GPIO_Structure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Structure.GPIO_OType = GPIO_OType_PP;
GPIO_Structure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Structure.GPIO_Pin = R1_PIN;
GPIO_Init(R1_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R2_PIN;
GPIO_Init(R2_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R3_PIN;
GPIO_Init(R3_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = R4_PIN;
GPIO_Init(R4_GPIO_PORT, &GPIO_Structure);
//============ Column ================
GPIO_Structure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Structure.GPIO_OType = GPIO_OType_PP;
GPIO_Structure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Structure.GPIO_Pin = C1_PIN;
GPIO_Init(C1_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C2_PIN;
GPIO_Init(C2_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C3_PIN;
GPIO_Init(C3_GPIO_PORT, &GPIO_Structure);
GPIO_Structure.GPIO_Pin = C4_PIN;
GPIO_Init(C4_GPIO_PORT, &GPIO_Structure);
GPIO_ResetBits(C1_GPIO_PORT, C1_PIN);
GPIO_ResetBits(C2_GPIO_PORT, C2_PIN);
GPIO_ResetBits(C3_GPIO_PORT, C3_PIN);
GPIO_ResetBits(C4_GPIO_PORT, C4_PIN);
}
/**
* @brief Configure the GPIO, and detect whether the key was pressed down
* @param None
* @retval None
*/
void KEY_GPIO_ConfigAndDetect(void)
{
u8 TEMP_COMBINE = 0, TEMP_ROCI = 0, TEMP_RICO = 0;
GPIO_RCC_Config();
printf("\nWhy so serious ?\tThe game just begin!");
while(1)
{
ROCI_GPIO_Config();
TEMP_ROCI = (u8)(((u8)DETECT_C1) << 3) |
(((u8)DETECT_C2) << 2) |
(((u8)DETECT_C3) << 1) |
(((u8)DETECT_C4) << 0);
if(TEMP_ROCI != 0x0f)
{
Delay(1000); // Eliminate the shaking. The parameter's unit is 10us
if(TEMP_ROCI != 0x0f) // Ensure one of the keys was pressed down indeed.
{
RICO_GPIO_Config();
TEMP_RICO = (u8)(((u8)DETECT_R1) << 3) |
(((u8)DETECT_R2) << 2) |
(((u8)DETECT_R3) << 1) |
(((u8)DETECT_R4) << 0);
TEMP_COMBINE = (u8)((TEMP_ROCI << 4) | TEMP_RICO); // Combine the two situation and we can know which key was pressed down.
switch(TEMP_COMBINE)
{
case S1:
printf("\nS1 was pressed down!");
break;
case S2:
printf("\nS2 was pressed down!");
break;
case S3:
printf("\nS3 was pressed down!");
break;
case S4:
printf("\nS4 was pressed down!");
break;
case S5:
printf("\nS5 was pressed down!");
break;
case S6:
printf("\nS6 was pressed down!");
break;
case S7:
printf("\nS7 was pressed down!");
break;
case S8:
printf("\nS8 was pressed down!");
break;
case S9:
printf("\nS9 was pressed down!");
break;
case S10:
printf("\nS10 was pressed down!");
break;
case S11:
printf("\nS11 was pressed down!");
break;
case S12:
printf("\nS12 was pressed down!");
break;
case S13:
printf("\nS13 was pressed down!");
break;
case S14:
printf("\nS14 was pressed down!");
break;
case S15:
printf("\nS15 was pressed down!");
break;
case S16:
printf("\nS16 was pressed down!");
break;
default:
break;
}
while(TEMP_RICO != 0x0F)
{
TEMP_RICO = (u8)(((u8)DETECT_R1)<<3) |
(((u8)DETECT_R2)<<2) |
(((u8)DETECT_R3)<<1) |
(((u8)DETECT_R4)<<0);
}
}
}
}
}