STM32单按键矩阵键盘轮询读取键值教程

一、单个按键读取键值——轮询方式

1.初始化

void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStructure);	
}

2.获取键值操作

        重点理解按键消抖的过程:当我们读取到键值变化时,先延迟20ms之后,检测按键是否松手,若没有就一直等待松手,直到松手之后,在延迟20ms,然后再给变量赋键值。

uint8_t Get_KeyNum(void)
{
	uint8_t keynum=0;
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)//检测按键是否按下
	{
		Delay_ms(20);//延迟20ms等待按下的机械抖动消除
		while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0);//等待按键松手,若不松手则一直while循环等待松手
		Delay_ms(20);//延迟20ms等待松开的机械抖动消除
		keynum=1;//给变量赋键值
	}
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0);
		Delay_ms(20);
		keynum=2;
	}
	return keynum;
}

3.主函数中调用

        通过轮询的方式检测按键,这里注意每次调用函数的时候当按键不按下的时候,键值一直时0。某一时刻按键按下之后便会执行对应的操作,但注意下一次循环依然会把变量keynum赋值为0.

int main(void)
{
	OLED_Init();
	Key_Init();
	Led_Init();
	while(1)
	{
		keynum=Get_KeyNum();
		if(keynum==1)
		{
			LedB_Turn();
		}
		if(keynum==2)
		{
			LedE_Turn();
		}

		OLED_ShowHexNum(1,1,keynum,4,OLED_8X16);
		OLED_Update();
		if(keynum!=0)Delay_ms(500);
		
	}
	
}

二、矩阵按键读取键值——轮询方式

原理相同,但是要对键盘进行扫描,这里采用行扫描的方式进行:

1.端口定义:

#define   C4   GPIO_Pin_0
#define   C3   GPIO_Pin_1
#define   C2   GPIO_Pin_2
#define   C1   GPIO_Pin_3
#define   R4   GPIO_Pin_4
#define   R3   GPIO_Pin_5
#define   R2   GPIO_Pin_6
#define   R1   GPIO_Pin_7

2.端口初始化 

这里注意如果是按行扫描,那么控制列的端口需要配置成输入模式,控制行的端口配置成输出模式

void Matrix_Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=C1|C2|C3|C4;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=R1|R2|R3|R4;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

3.按键扫描——按行扫描

uint8_t Matrix_Key_GetNum(void)
{
	uint8_t keynum=0;
	GPIO_Write(GPIOA,0X00FF);
	GPIO_WriteBit(GPIOA,R1,Bit_RESET);
	if(GPIO_ReadInputDataBit(GPIOA,C1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C1)==0);Delay_ms(20);keynum=16;}
	if(GPIO_ReadInputDataBit(GPIOA,C2)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C2)==0);Delay_ms(20);keynum=15;}
	if(GPIO_ReadInputDataBit(GPIOA,C3)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C3)==0);Delay_ms(20);keynum=14;}
	if(GPIO_ReadInputDataBit(GPIOA,C4)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C4)==0);Delay_ms(20);keynum=13;}

	GPIO_Write(GPIOA,0X00FF);
	GPIO_WriteBit(GPIOA,R2,Bit_RESET);
	if(GPIO_ReadInputDataBit(GPIOA,C1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C1)==0);Delay_ms(20);keynum=12;}
	if(GPIO_ReadInputDataBit(GPIOA,C2)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C2)==0);Delay_ms(20);keynum=11;}
	if(GPIO_ReadInputDataBit(GPIOA,C3)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C3)==0);Delay_ms(20);keynum=10;}
	if(GPIO_ReadInputDataBit(GPIOA,C4)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C4)==0);Delay_ms(20);keynum=9;}

	GPIO_Write(GPIOA,0X00FF);
	GPIO_WriteBit(GPIOA,R3,Bit_RESET);
	if(GPIO_ReadInputDataBit(GPIOA,C1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C1)==0);Delay_ms(20);keynum=8;}
	if(GPIO_ReadInputDataBit(GPIOA,C2)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C2)==0);Delay_ms(20);keynum=7;}
	if(GPIO_ReadInputDataBit(GPIOA,C3)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C3)==0);Delay_ms(20);keynum=6;}
	if(GPIO_ReadInputDataBit(GPIOA,C4)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C4)==0);Delay_ms(20);keynum=5;}

	GPIO_Write(GPIOA,0X00FF);
	GPIO_WriteBit(GPIOA,R4,Bit_RESET);
	if(GPIO_ReadInputDataBit(GPIOA,C1)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C1)==0);Delay_ms(20);keynum=4;}
	if(GPIO_ReadInputDataBit(GPIOA,C2)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C2)==0);Delay_ms(20);keynum=3;}
	if(GPIO_ReadInputDataBit(GPIOA,C3)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C3)==0);Delay_ms(20);keynum=2;}
	if(GPIO_ReadInputDataBit(GPIOA,C4)==0){Delay_ms(20);while(GPIO_ReadInputDataBit(GPIOA,C4)==0);Delay_ms(20);keynum=1;}

	return keynum;
}

4.主循环调用验证

#include "main.h"
uint8_t keynum;
int main(void)
{
	OLED_Init();
	Matrix_Key_Init();
	while(1)
	{
		keynum=Matrix_Key_GetNum();
		if(keynum!=0)
		{
			OLED_ShowString(1,1,"KEYNUM: ",OLED_8X16);
			OLED_ShowNum(66,1,keynum,2,OLED_8X16);
			OLED_Update();	
		}
		
	}
}

PS:最后发现键值反了,最后倒着把键值改了,不过影响不大

三、矩阵键盘密码锁

实现密码锁逻辑(key1-10表示数字,10代表0,11为确认,12为退格)

#include "main.h"
uint8_t keynum,count;
uint16_t user_input,password;
int main(void)
{
	OLED_Init();
	Matrix_Key_Init();
	OLED_ShowString(0,0,"PLEASE INPUT PASSWORD:",OLED_6X8);
	OLED_Update();
	password=3030;
	while(1)
	{
		OLED_ShowNum(0,32,count,4,OLED_8X16);
		OLED_Update();
		keynum=Matrix_Key_GetNum();
		if(keynum<=10 && keynum>0 &&count<4&&count>=0)
		{
			keynum%=10;
			user_input*=10;
			user_input+=keynum;
			OLED_ShowNum(0,16,user_input,4,OLED_8X16);
			OLED_Update();
			count++;
		}
		if(keynum==11)
		{
				if(user_input==password)
			{
				OLED_Clear();
				OLED_ShowString(0,0,"PASSWORD RIGHT!",OLED_6X8);
				OLED_Update();
				Delay_ms(2000);
				count=user_input=keynum=0;
				OLED_ShowString(0,0,"PLEASE INPUT PASSWORD:",OLED_6X8);
				OLED_Update();

			}
			else
			{
				OLED_Clear();
				OLED_ShowString(0,0,"PASSWORD ERRO!",OLED_6X8);
				OLED_Update();
				Delay_ms(2000);
				count=user_input=keynum=0;
				OLED_ShowString(0,0,"PLEASE INPUT PASSWORD:",OLED_6X8);
				OLED_Update();
			}
		}
		if(keynum==12)
		{
			user_input/= 10;
			OLED_ShowNum(0,16,user_input,4,OLED_8X16);
			OLED_Update();
			count--;
		}
	}
}

作者:Mistletoe29

物联沃分享整理
物联沃-IOTWORD物联网 » STM32单按键矩阵键盘轮询读取键值教程

发表回复