目录
一、介绍
矩阵键盘,又称为行列式键盘,是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。在行线和列线的每一个交叉点上设置一个按键,因此键盘中按键的个数是4×4个。这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率,节约单片机的资源。(8引脚控制16按键)
哔哩哔哩视频:
4×4矩阵键盘详解(STM32)
(资料分享见文末)
二、传感器原理
1.原理图
在硬件上,4条行线连接到微控制器的输出引脚,而4条列线连接到微控制器的输入引脚,每个按键位于行线和列线的交叉点上
2.工作原理介绍
行线的主要功能是向列线发送扫描信号。当某一行线被设置为低电平时,与之相交的列线会被检测(若相对应的按键被按下,列线被检测为低电平)以判断是否有按键被按下。
通过依次将每一行线设置为低电平(可以逐行扫描键盘)。当检测到列线上有低电平时,可以确定被按下的按键位于当前选中的行上。若列线上无低电平,那么将此行线设置为高电平,下一行设置为低电平,进行新一轮按键检测。
三、程序设计
1.使用STM32F103C8T6读取4×4矩阵键盘采集的按键数据,通过串口发送至电脑
2.将读取得到按键信息数据同时在OLED上显示
|-----------|-----|
| BUTTON_行1 | PA0 |
| BUTTON_行2 | PA1 |
| BUTTON_行3 | PA2 |
| BUTTON_行4 | PA3 |
| BUTTON_列1 | PA4 |
| BUTTON_列2 | PA5 |
| BUTTON_列3 | PA6 |
| BUTTON_列4 | PA7 |
main.c文件
cpp
#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "button4_4.h"
/*****************辰哥单片机设计******************
STM32
* 项目 : 4×4矩阵键盘实验
* 版本 : V1.0
* 日期 : 2024.9.5
* MCU : STM32F103C8T6
* 接口 : 参看button4_4.h
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
u16 value;
int main(void)
{
SystemInit();//配置系统时钟为72M
delay_init(72);
LED_Init();
LED_On();
Button4_4_Init();
OLED_Init();
delay_ms(1000);
OLED_Clear();
//显示"按键:"
OLED_ShowChinese(0,0,0,16,1);
OLED_ShowChinese(16,0,1,16,1);
OLED_ShowChar(40,0,':',16,1);
while (1)
{
value = Button4_4_Scan();
if(value!=0)
{
OLED_ShowNum(60,0,value,2,16,1);
LED_Toggle();
delay_ms(500);
}
else
OLED_ShowString(60,0," ",16,1);
}
}
button4_4.h文件
cpp
#ifndef __BUTTON4_4_H
#define __BUTTON4_4_H
#include "stm32f10x.h"
#include "delay.h"
#include "math.h"
/*****************辰哥单片机设计******************
STM32
* 文件 : 4×4矩阵键盘h文件
* 版本 : V1.0
* 日期 : 2024.9.5
* MCU : STM32F103C8T6
* 接口 : 见代码
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
/***************根据自己需求更改****************/
// 4×4矩阵键盘 GPIO宏定义
#define BUTTON_GPIO_CLK RCC_APB2Periph_GPIOA
#define BUTTON_ROW1_GPIO_PORT GPIOA
#define BUTTON_ROW1_GPIO_PIN GPIO_Pin_0
#define BUTTON_ROW2_GPIO_PORT GPIOA
#define BUTTON_ROW2_GPIO_PIN GPIO_Pin_1
#define BUTTON_ROW3_GPIO_PORT GPIOA
#define BUTTON_ROW3_GPIO_PIN GPIO_Pin_2
#define BUTTON_ROW4_GPIO_PORT GPIOA
#define BUTTON_ROW4_GPIO_PIN GPIO_Pin_3
#define BUTTON_COL1_GPIO_PORT GPIOA
#define BUTTON_COL1_GPIO_PIN GPIO_Pin_4
#define BUTTON_COL2_GPIO_PORT GPIOA
#define BUTTON_COL2_GPIO_PIN GPIO_Pin_5
#define BUTTON_COL3_GPIO_PORT GPIOA
#define BUTTON_COL3_GPIO_PIN GPIO_Pin_6
#define BUTTON_COL4_GPIO_PORT GPIOA
#define BUTTON_COL4_GPIO_PIN GPIO_Pin_7
/*********************END**********************/
void Button4_4_Init(void);
int Button4_4_Scan(void);
#endif
button4_4.c文件
cpp
#include "button4_4.h"
/*****************辰哥单片机设计******************
STM32
* 文件 : 4×4矩阵键盘c文件
* 版本 : V1.0
* 日期 : 2024.9.5
* MCU : STM32F103C8T6
* 接口 : 见代码
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
struct IO_PORT
{
GPIO_TypeDef *GPIO_x;
unsigned short GPIO_pin;
};
static struct IO_PORT KEY_OUT[4] = {
{BUTTON_ROW1_GPIO_PORT, BUTTON_ROW1_GPIO_PIN},
{BUTTON_ROW2_GPIO_PORT, BUTTON_ROW2_GPIO_PIN},
{BUTTON_ROW3_GPIO_PORT, BUTTON_ROW3_GPIO_PIN},
{BUTTON_ROW4_GPIO_PORT, BUTTON_ROW4_GPIO_PIN}
};
static struct IO_PORT KEY_IN[4] = {
{BUTTON_COL1_GPIO_PORT, BUTTON_COL1_GPIO_PIN},
{BUTTON_COL2_GPIO_PORT, BUTTON_COL2_GPIO_PIN},
{BUTTON_COL3_GPIO_PORT, BUTTON_COL3_GPIO_PIN},
{BUTTON_COL4_GPIO_PORT, BUTTON_COL4_GPIO_PIN}
};
unsigned char key[4][4];
void Button4_4_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
unsigned char i;
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
RCC_APB2PeriphClockCmd(BUTTON_GPIO_CLK, ENABLE);
for(i=0;i<4;i++)
{
GPIO_InitStructure.GPIO_Pin = KEY_OUT[i].GPIO_pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEY_OUT[i].GPIO_x, &GPIO_InitStructure);
}
for(i=0;i<4;i++)
{
GPIO_InitStructure.GPIO_Pin = KEY_IN[i].GPIO_pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEY_IN[i].GPIO_x, &GPIO_InitStructure);
}
for(i = 0; i < 4; i++)
{
GPIO_SetBits(KEY_OUT[i].GPIO_x, KEY_OUT[i].GPIO_pin);
}
}
int Button4_4_Scan(void)
{
unsigned char i, j;
for(i = 0; i < 4; i++)
{
delay_ms(5);
GPIO_ResetBits(KEY_OUT[i].GPIO_x, KEY_OUT[i].GPIO_pin);
for(j = 0; j < 4; j++)
{
delay_ms(5);
if(GPIO_ReadInputDataBit(KEY_IN[j].GPIO_x, KEY_IN[j].GPIO_pin) == 0)
{
key[i][j] = 1;
}else{
key[i][j] = 0;
}
}
GPIO_SetBits(KEY_OUT[i].GPIO_x, KEY_OUT[i].GPIO_pin);
}
if(key[0][0]==1)return 13;
else if(key[0][1]==1)return 14;
else if(key[0][2]==1)return 15;
else if(key[0][3]==1)return 16;
else if(key[1][0]==1)return 9;
else if(key[1][1]==1)return 10;
else if(key[1][2]==1)return 11;
else if(key[1][3]==1)return 12;
else if(key[2][0]==1)return 5;
else if(key[2][1]==1)return 6;
else if(key[2][2]==1)return 7;
else if(key[2][3]==1)return 8;
else if(key[3][0]==1)return 1;
else if(key[3][1]==1)return 2;
else if(key[3][2]==1)return 3;
else if(key[3][3]==1)return 4;
else return 0;
}