STM32 >> 矩阵键盘(代码风格优美,简明易懂)

时间:2019-01-23
本文章向大家介绍STM32 >> 矩阵键盘(代码风格优美,简明易懂),主要包括STM32 >> 矩阵键盘(代码风格优美,简明易懂)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本文有关矩阵键盘的使用原理适用于所有微机控制器,同时也适用于所有规格的矩阵键盘。

key.h

/**
  ******************************************************************************
  * @file    bsp_key.h
  * @author  Waao
  * @version V1.0.0
  * @date    20-Dec-2018
  * @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>


// 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
#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)

#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

有关输入输出管脚的选择可以多试验几组,有的管脚即使你配置成上拉输入,当你松开按键之后依然不会返回高电平,我在此就因为这个问题被卡了一阵子


关于我的矩阵键盘检测的原理简明阐述如下

  1. 首先设置为行输出低电平,列上拉输入(即无外部干扰时保持高电平);
  2. 检测到按键按下,此时通过检测列的电平情况从而得知哪一列有按键被按下;
  3. 然后确定有按键被按下后,设置为列输出低电平,行上拉输入;
  4. 通过检测行的电平情况从而得知哪一行有按键被按下;
  5. 最后通过“不平行的两条直线相交于一点”原理,推知具体被按下的按键。

key.c

/**
  ******************************************************************************
  * @file    bsp_key.c
  * @author  Waao
  * @version V1.0.0
  * @date    20-Dec-2018
  * @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.
			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);
				}
			}
		}
	}
}