STM32F103 矩阵键盘4*4 16*16等任意矩阵 按键扫描程序

基于STM32的按键扫描测试程序(学习记录):

目录:

  1. 源码;
  2. 4x4按键原理;
  3. 按键扫描逻辑;

Tips:

  1. 粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文字符;
  2. 程序使用嵌套循环实现4x4按键扫描,如果IO口设置过乱时,将循环拆分即可;

key4x4.h源文件

#ifndef __KEY4x4_H
#define __KEY4x4_H	 
#include "sys.h"
 
#define KEY_X(X)	PEin(X)				// 尽量避免使用PD以上GPIO,便于移植;
#define KEY_Y(Y)	PEout(Y)

#define ALL_DOWN_KEY_Y	{	KEY_Y(11) = 0; KEY_Y(12) = 0; KEY_Y(13) = 0; KEY_Y(14) = 0;}
 
void KEY4x4_Init(void);		// IO口初始化
u8 KEY4x4_Scan(void);  		// 矩阵按键反馈函数	// 可配置任意矩阵按键使用!!
u8 KEY16_Scan(void);

/**************
其他按键扫描方案:
按键使用8个输入IO口, 且所有IO口一端接VCC/VSS;

程序框架:	
	扫描检测哪两个IO口输入高/低电平;VCC/VSS
	根据对应坐标,return对应编号;
**************/

#endif

key4x4.c源文件

#include "stm32f10x.h"
#include "key4x4.h"
#include "sys.h" 
#include "delay.h"
#include "usart.h"


/*************************
X:
	PEin	7-10
Y:
	PEout	11-14
*************************/


// 矩阵按键初始化函数
void KEY4x4_Init(void)
{
		GPIO_InitTypeDef GPIO_InitStructure;

		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);

		GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//KEY0-KEY1
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成下拉输入
		GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE

		GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;				 //LED0-->PB.5 端口配置
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
		GPIO_Init(GPIOE, &GPIO_InitStructure);					 		//根据设定参数初始化GPIOE
}

// 使所有输出拉低;初始化;		// 可以使用define宏定义,执行速度更快,不用跳转函数!!
static void KEY_ALL_Pull_Down(void)
{
	KEY_Y(11) = 0;
	KEY_Y(12) = 0;
	KEY_Y(13) = 0;
	KEY_Y(14) = 0;
}

// 4x4按键扫描函数
// 使用一个嵌套循环,完成扫描X和Y;
// 原理: 通过Y 依次输出高电平,
//				扫描X 那个IO口输入高电平;
// X轴:输入检查、扫描;
// Y轴:设置输出状态;
// 该函数适合任意排列矩阵按键,只需修改循环中对应编号!!
// 注意: 1. 改变IO口时,该函数还需要改变循环中IO口编号;(可以定义好IO口编号,便于修改)
//				2. 该函数同样有优先级问题! 即同时按下时,只反馈先被扫描到的(0-15标号最小的)
//				3. 函数同一坐标轴的IO口编号必须相邻或能有 规律递增可寻;(否则无法用循环判断)
//				4. 暂时未添加功能(模式):	按键复用 和 长按;
// 2020-11-13		返回值调整为:1-16
// 11/14 不支持连按;解决重复反馈的问题;
u8 KEY4x4_Scan(void)
{
	int i,j;
	u8 IO_Sign = 0;				// 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
	static key_up = 1;
	
	//KEY_ALL_Pull_Down();										// 初始化所有按键输出拉低;
	
	for (i = 11; i <= 14; i++)							// Y输出IO口编号;
		for (j = 7; j <= 10; j++,IO_Sign++)		// X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
		{
			KEY_Y(i) = 1;			// 使PEout(i)输出高电平;
			
			if (KEY_Y(i))			// 扫描Y输出高电平, 可以取消此判断; 因为必须输出高电平时,才能正常判断!!
			{
				if (KEY_X(j) && key_up)		// 当输入检查到高电平时;
				{
					key_up = 0;
					printf("按键扫描反馈: %d  \r\n",IO_Sign);
					return IO_Sign;
				}
				else if (!KEY_X(7)&&!KEY_X(8)&&!KEY_X(9)&&!KEY_X(10))			// 当所有输入检测到低电平时,再次使能按键; 防止重复反馈
				{
					key_up = 1;
					KEY_ALL_Pull_Down();										// 初始化所有按键输出拉低(低电平);必须在此位置;
				}
			}
			else
				printf("PEout:IO口%d输出异常!  \r\n ", i);
		}
		
	delay_ms(10);					// 按键防抖;
}


/******************************************标准扫描函数*********************************************/
// 支持连按
u8 KEY16_Scan(void)
{
	int i,j;
	u8 IO_Sign = 0;				// 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
	
	ALL_DOWN_KEY_Y													// 初始化所有按键输出拉低;
	
	for (i = 11; i <= 14; i++)							// Y输出IO口编号;
		for (j = 7; j <= 10; j++,IO_Sign++)		// X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
		{
			KEY_Y(i) = 1;			// 使PEout(i)输出高电平;

			if (KEY_X(j))			// 当输入检查到高电平时;
				return IO_Sign;
		}
		
	delay_ms(20);					// 按键防抖;		// 连按延时;
}

*4x4按键原理图
在这里插入图片描述

  1. 按键工作原理:
    当按键被按下时,相连的电路导通;即S1按下时,位于0行0列的线短路,使标号4和5对应的IO口相连(导通);
    最后通过扫描检测输入输出状态即可判断出对应按键被按下;

  2. 程序设计思路:
    程序通过依次使标号1、2、3、4(列0-3)输出高电平,判断5/6/7/8(行0-3)状态;完成按键扫描;

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值