【STM32-矩阵键盘】

本文介绍了4*4矩阵键盘的连接方式,通过PD0-PD7端口控制行和列,阐述了按键检测的行列扫描方法,包括确定列值和行值的步骤,以及如何通过消除抖动来识别按键。同时提供了Key模块的C代码实现,包括Key_Init1和Key_Init2函数,以及Key_Scan函数来获取按键值。文章强调了在学习过程中不断实践和总结的重要性。
该文章已生成可运行项目,

目录

1.矩阵键盘简介

2.原理描述

3.代码编写

4.自我总结

1.矩阵键盘简介

在这里插入图片描述

此处我们采用4*4的矩阵键盘,需要8个端口与单片机连接
4个控制行,4个控制列

2.原理描述

很多人不清楚八个引脚怎么连接,这里我采取PD0-PD7
PD0-PD3控制1-4行PD4-PD7控制1-4列

在这里插入图片描述

如何确定我们按下的是哪个按键呢?
一.确定列值
1.将PD0-PD3作为输出PD4-PD7作为输入
2.输入均配置为上拉,即都为1输出拉低,即为0
3.当按下某个按键后,将该按键所连接的0,例如按下S1

在这里插入图片描述

二.确定行值
1.将PD0-PD3作为输入PD4-PD7作为输出
2.输入均配置为上拉,即都为1输出拉低,即为0
3.当按下某个按键后,将该按键所连接的0,例如按下S1

在这里插入图片描述

第一张图可知:(列值) col=0x1110_0000,即col=0xe0
第二张图可知:(行值) row=0x0000_1110,即row=0x0e
综合起来就得到了按键S1对应的键值:res=col|row=0xee
其余所有按键均按此逻辑推得

3.代码编写

大体思路就是建立一个Key模块,包含Key.c和Key.h,最后在main里调用即可

key.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

void Key_Init1(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	//PD0,1,2,3作为输出,PD4,5,6,7作为输入,且上拉,默认为1
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStructure);
	//0,1,2,3置低电位,即0
	GPIO_ResetBits(GPIOD,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStructure);
}

void Key_Init2(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
	//PD0,1,2,3作为输入,且上拉,默认为1;PD4,5,6,7作为输出,且置0
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStructure);
	GPIO_ResetBits(GPIOD,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}

uint16_t Key_Scan(void){
	uint16_t row,col,res;//row为行值,col为列值,res=row|col,用于主函数判断
	Key_Init1();//此时PD7...PD0为0x11110000,即0xf0
	col=GPIO_ReadInputData(GPIOD);	//读取上面的0xf0
	col=col&0xf0;//没有任何按键按下那么col必然与0xf0相等
	if(col!=0xf0)//说明可能有按键按下,需要消除抖动,进一步确定
	{
		Delay_ms(20);//消除抖动
		col=GPIO_ReadInputData(GPIOD);
		col=col&0xf0;
		if(col!=0xf0)//若还是不相等,表示必然有按键按下
		{
			col=GPIO_ReadInputData(GPIOD);
			col=col&0xf0;//如果S1按下,那此处就是0xe0&0xf0=0xe0
		}
		Key_Init2();//此时PD7...PD0为0x00001111,即0x0f
		row=GPIO_ReadInputData(GPIOD);//读取上面的0x0f
		row=row&0x0f;//没有任何按键按下那么row必然与0x0f相等
		if(row!=0x0f)//说明可能有按键按下,需要消除抖动,进一步确定
		{
			Delay_ms(20);//消除抖动
			row=GPIO_ReadInputData(GPIOD);
			row=row&0x0f;
			if(row!=0x0f)//若还是不相等,表示必然有按键按下
			{
				row=GPIO_ReadInputData(GPIOD);
				row=row&0x0f;//若S1按下,那此处就是0x0e&0x0f=0x0e
			}
			res=row|col;//0xe0|0x0e=0xee,表示按键S1对应的键值为0xee
		}
	}		
		return res;
}

key.h

#ifndef __KEY_H
#define __KEY_H
void Key_Init1(void);//获取列值
void Key_Init2(void);//获取行值
uint16_t Key_Scan(void);//获取按键值
#endif

main

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Key.h"


uint16_t keyValue=0;
int main(void)
{
	
	while(1)
	{
		keyValue=Key_Scan();//获取按键的键值
		switch(keyValue)			//根据键值确定按下的按钮
		{
			case 0xee:/**待调用函数**/;break;
			case 0xde:;break;
			case 0xbe:;break;
			case 0x7e:;break;
			
			case 0xed:;break;
			case 0xdd:;break;
			case 0xbd:;break;
			case 0x7d:;break;
			
			case 0xeb:;break;
			case 0xdb:;break;
			case 0xbb:;break;
			case 0x7b:;break;
			
			case 0xe7:;break;
			case 0xd7:;break;
			case 0xb7:;break;
			case 0x77:;break;
			
			default:break;
			
		}
	}
}
4.自我总结

学习单片机的外设时,需要了解该外设的结构原理如何驱动该外设
我在学习矩阵键盘的过程中,也是屡次试错,有时候是线接的不对,有时候是代码写的不对,不过我也在一次一次试错中找到了正确的解,希望大家在学习的过程中敢于试错不断练习善于总结,我们下期见!

本文章已经生成可运行项目
### 矩阵键盘的原理 矩阵键盘是一种将多个按键按照行列排列的方式,以减少对单片机I/O口占用的设计。每个按键位于行线和列线的交叉点上,当某个按键被按下时,对应的行线和列线会导通,导致电平发生变化。通过检测这些变化,可以确定哪个按键被按下 [^2]。 例如,在一个4x4的矩阵键盘中,有4条行线和4条列线,总共可以连接16个按键。这种结构相比独立按键大大节省了I/O口资源,非常适合按键数量较多的应用场景 [^2]。 ### 矩阵键盘的工作原理详解 矩阵键盘的基本工作原理是通过逐行或逐列扫描的方式来检测按键的状态。通常有两种主要的识别方法:**行扫描法**和**线反转法**。具体来说: - **行扫描法**:首先将所有列线设置为高电平,然后依次将每一行设置为低电平,同时检测各列是否有低电平信号。如果有某一列变为低电平,则说明该行与该列交叉点的按键被按下。 - **线反转法**:这种方法通过反转行线和列线的角色来提高效率,从而减少对MCU的占用时间 [^2]。 需要注意的是,当多个按键同时按下时,可能会出现“鬼键”问题,即无法准确判断哪些按键真正被按下。因此在设计时需要考虑防干扰措施或者使用硬件去抖动电路 [^5]。 ### 矩阵键盘的使用方法 #### 硬件连接 矩阵键盘一般连接到单片机的一个端口(如P1口),其中一部分引脚作为行线,另一部分作为列线。例如,在一个4x4的矩阵键盘中,P1.0-P1.3可以作为行线,而P1.4-P1.7作为列线 [^1]。 #### 软件编程 软件编程的核心在于实现按键的扫描和识别。以下是一个简单的C语言代码示例,用于51单片机上的矩阵键盘扫描: ```c #include <reg51.h> #define KEYPORT P1 // 定义KEYPORT为P1口 unsigned char key_scan() { unsigned char row, col, key; for (col = 0; col < 4; col++) { // 遍历每一列 KEYPORT = ~(1 << (col + 4)); // 设置当前列为低电平 for (row = 0; row < 4; row++) { // 检测每一行 if ((KEYPORT & (1 << row)) == 0) { // 如果某一行变为低电平 key = row * 4 + col; // 计算按键值 return key; // 返回按键值 } } } return 0xFF; // 没有按键按下返回0xFF } void main() { while (1) { unsigned char key = key_scan(); // 扫描键盘 if (key != 0xFF) { // 处理按键事件 } } } ``` 上述代码实现了基本的行扫描法。程序通过循环遍历每一列,并将当前列设置为低电平,然后检测各行是否有低电平信号。如果检测到某一行变为低电平,则说明该行与当前列交叉点的按键被按下,并计算出对应的按键值 [^4]。 ### 总结 矩阵键盘通过行列式结构有效提高了单片机系统中I/O口的利用率,适用于按键数量较多的情况。其核心在于通过逐行或逐列扫描的方法检测按键状态,结合适当的软件算法来识别按键位置。尽管存在一定的复杂性,但通过合理的设计和编程,可以实现高效可靠的按键检测。 ---
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值