矩阵键盘模块的设计原理与使用

目录

设计图

原理:

代码部分:KeyMatrix.c 文件

主函数main.c


常见的矩阵键盘是4X4的,如果按照一个按键开关对应一个IO口,那得需要16的IO口,但是STM32单片机IO口总共就那么几个,如果按键使用了这么多,其他的模块就难以使用。

如下是一个4X4的矩阵键盘,但是只需要8个IO口

设计图

分四行四列,首先,对行判断,看四行中哪个被触发了,再对列判断,看四列中哪个被触发了,行和列对应起来,就是4X4坐标中的某一个位置。

原理:

行判断:首先对四行都设置为上拉输入,四列设置为低电平,当某一个开关按下时,则该行会判别到低电平,从而让我们知道是哪个按键被触发了。

列判断:再改变输入输出模式,让四列为上拉输入,四行为低电平,当某一个开关被按下时,则该列会被判别到低电平,从而让我们知道是哪个按键被触发了。

代码部分:KeyMatrix.c 文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"                 //延时用 可以晚上查一下  很多的
#include "OLED.h"                  //显示用的 OLED显示屏
#define Pin_Row_1  GPIO_Pin_9
#define Pin_Row_2  GPIO_Pin_10
#define Pin_Row_3  GPIO_Pin_11
#define Pin_Row_4  GPIO_Pin_12
//上面是1~4行,下面是1~4列
#define Pin_Column_1  GPIO_Pin_0
#define Pin_Column_2  GPIO_Pin_1
#define Pin_Column_3  GPIO_Pin_2
#define Pin_Column_4  GPIO_Pin_3
#define Port_GPIO  GPIOA  

//原理:默认四个接收口为高电平,另外四个输出口为低电平,
//如果按键接通,接收口就回变成低电平,如果变低电平,则给标志Key改变数值
//测量行或者列的电位后,反转接受和输出,再测量列或者行电位。

void KeyMatrix_Init_1(void)//行判断 的基础设置
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure1;
	GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IPU; //对行全设置为上拉输入
	GPIO_InitStructure1.GPIO_Pin = Pin_Row_1|Pin_Row_2|Pin_Row_3|Pin_Row_4; 
	GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Port_GPIO,&GPIO_InitStructure1);
	
	GPIO_InitTypeDef GPIO_InitStructure2;
	GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_Out_PP ; //对列全设置为输出模式
	GPIO_InitStructure2.GPIO_Pin =  Pin_Column_1|Pin_Column_2|Pin_Column_3| Pin_Column_4;   
	GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Port_GPIO,&GPIO_InitStructure2);
}
int key1=0;
int KeyMatrix_Get_1(void)//行判断
{
	KeyMatrix_Init_1();
	GPIO_WriteBit(Port_GPIO,Pin_Column_1,Bit_RESET);   //对1~4列都设置为低电平
	GPIO_WriteBit(Port_GPIO,Pin_Column_2,Bit_RESET);
	GPIO_WriteBit(Port_GPIO,Pin_Column_3,Bit_RESET);
	GPIO_WriteBit(Port_GPIO,Pin_Column_4,Bit_RESET);   
	//Delay_ms(10);消除抖动
	if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Row_1)==0)  //如果第一行为低电平 
	{
		Delay_ms(10); key1=4;                          //则给标志key1改变值
	} 
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Row_2)==0) //如果第二行改变值  以下同理
	{
		Delay_ms(10);key1=3;
	}
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Row_3)==0)
	{
		Delay_ms(10);key1=2;
	}
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Row_4)==0)
	{
		Delay_ms(10);key1=1;
	}
	else {key1=0;}  //如果都没被按下,则输出为0
	return key1;	
}
void KeyMatrix_Init_2(void)  //列判断 的基础设置
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure1;
	GPIO_InitStructure1.GPIO_Mode =  GPIO_Mode_Out_PP; //对四行都设置为输出模式
	GPIO_InitStructure1.GPIO_Pin = Pin_Row_1|Pin_Row_2|Pin_Row_3|Pin_Row_4; //1~4行输出
	GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Port_GPIO,&GPIO_InitStructure1);
	
	GPIO_InitTypeDef GPIO_InitStructure2;
	GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_IPU ; //1~4列上拉输入
	GPIO_InitStructure2.GPIO_Pin =  Pin_Column_1|Pin_Column_2|Pin_Column_3| Pin_Column_4;
	GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Port_GPIO,&GPIO_InitStructure2);
}
int key2=0;
int KeyMatrix_Get_2(void)//列判断
{
	KeyMatrix_Init_2();
	GPIO_WriteBit(Port_GPIO,Pin_Row_1,Bit_RESET);  //对1~4行设置为低电平
	GPIO_WriteBit(Port_GPIO,Pin_Row_2,Bit_RESET);
	GPIO_WriteBit(Port_GPIO,Pin_Row_3,Bit_RESET);
	GPIO_WriteBit(Port_GPIO,Pin_Row_4,Bit_RESET);
	//Delay_ms(10);消除抖动
	if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Column_1)==0) //如果第一列为低电平 
	{
		Delay_ms(10);key2=4;
	}
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Column_2)==0)
	{
		Delay_ms(10);key2=3;
	}
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Column_3)==0)
	{
		Delay_ms(10);key2=2;
	}
	else if(GPIO_ReadInputDataBit(Port_GPIO,Pin_Column_4)==0)
	{
		Delay_ms(10);key2=1;
	}
	else {key2=0;}  //如果都没被按下,则输出为0
	return key2;	
}
//综合行列电平,获得坐标值,比如(1,2)为键盘上的0数字的地方
int key_lie ,key_hang,key_all,key_flag;
int KeyMatrix_Get_All(void)
{
	key_lie=KeyMatrix_Get_1();  //得知哪行被按下了
	key_hang=KeyMatrix_Get_2(); //得知哪列被按下了
	key_all=key_lie+key_hang*10; //让行的值*10  变成两位数 用坐标会更好理解
	switch(key_all)  //判断坐标位置
	{
		case 11:key_flag=1;break;//功能1
		case 12:key_flag=2;break;//数字0
		case 13:key_flag=3;break;//功能2
		case 14:key_flag=4;break;//功能3
	
		case 21:key_flag=5;break;//数字1
		case 22:key_flag=6;break;//数字2
		case 23:key_flag=7;break;//数字3
		case 24:key_flag=8;break;//功能4
		
		case 31:key_flag=9;break;//数字4
		case 32:key_flag=10;break;//数字5  
		case 33:key_flag=11;break;//数字6
		case 34:key_flag=12;break;//功能5
		
		case 41:key_flag=13;break;//数字7
		case 42:key_flag=14;break;//数字8
		case 43:key_flag=15;break;//数字9
		case 44:key_flag=16;break;//功能6
		
		case 00:key_flag=0;break; 
	}
	return key_flag;
}

int key_value;
void KeyMatrix_Use(void)  //功能设置处,可以写这些功能都需要做什么
{
	key_value=KeyMatrix_Get_All(); //获得按键代表的值
	switch(key_value)
	{
		case 1:OLED_ShowString(1,1,"G1");break;
		case 2:OLED_ShowNum(1,1,0,1);break;
		case 3:OLED_ShowString(1,1,"G2");break;
		case 4:OLED_ShowString(1,1,"G3");break;
		
		case 5:OLED_ShowNum(1,1,1,1);break;
		case 6:OLED_ShowNum(1,1,2,1);break;
		case 7:OLED_ShowNum(1,1,3,1);break;
		case 8:OLED_ShowString(1,1,"G4");break;
		
		case 9:OLED_ShowNum(1,1,4,1);break;
		case 10:OLED_ShowNum(1,1,6,1);break; //5和6的时候设计板子设计反了
		case 11:OLED_ShowNum(1,1,5,1);break;
		case 12:OLED_ShowString(1,1,"G5");break;
		
		case 13:OLED_ShowNum(1,1,7,1);break;
		case 14:OLED_ShowNum(1,1,8,1);break;
		case 15:OLED_ShowNum(1,1,9,1);break;
		case 16:OLED_ShowString(1,1,"G6");break;
		
		case 0:OLED_ShowString(1,1,"  ");break;
	}
}

主函数main.c
 

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "KeyMatrix.h"
int main(void)
{
	OLED_Init();
	while(1)
	{
		KeyMatrix_Use();             //判断按键来实行不同功能
		OLED_ShowString(4,1,"ON");   //显示程序运行
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值