历史上的今天
今天是:2025年08月16日(星期六)
2019年08月16日 | 基于 STM32F407 使用 4*4 矩阵键盘
2019-08-16 来源:eefocus
写在前面:
这是我第一次开始写博客,可能写的不是很好,也请大家谅解。
本人现在大三,以前在学习过程中遇到过各种各样的问题,关于51单片机,STM32单片机,最近在学习ARM11的Tiny6410
以后还会更新一些C/C++/Qt等等方面的东西
关于写博客这件事,其实 一直想写博客记录下来,但是因为某些原因(懒),so , 没有写。现在开始,以后遇到单片机上或者编程上遇到的问题,
并且自己很好地解决了,我就会在这里记录下来。
希望通过博客记录我的学习历程并希望我所解决问题的过程能够帮到需要的人,一起加油吧!!!
我是在STM32F407开发板上使用的4*4 矩阵键盘
下面是我所使用的开发板

1、首先介绍一下4*4矩阵键盘扫描原理
呃。。。。。就不介绍了,[矩阵键盘原理描述](http://www.51hei.com/mcu/3815.html),这个写的挺好的
2、Cube配置

矩阵键盘从下到上依次接到STM32F407zg单片机的PD0~7引脚 ,其中,矩阵键盘下面的四个排针对应的是键盘的行(ROW)
上面四个对应列(COL) 这里我画了一张图来说明我所使用的

PD0-3依次对应3-0行 PD4-7依次对应0-3列 这张图里可以看到我画了两个箭头,下面就给大家说一下我的配置
配置PD0~3为推挽输出 PD4~7为下拉输入,下图是我在STM32CubeMX 5.1.0中配置的
上面的箭头,横向的表示是单片机输出给键盘的,竖向的是表示送给单片机的,也就是单片机配置的输入引脚
用来读取PD4~7的电平
3、程序编写
因为PD4~7为上拉输入,所以是处在一种高阻态(可以暂时理解为高电平,就是四列都为1)
我以扫描第一行为例讲解

上述是软件实现部分, GPIO->IDR和0xf7相与, 若是0xe7 则二进制位1110 0111,说明PD4变为了0,所以第一列的按键
s1按下
note:PD7对应二进制的最高位,PD0对应二进制的最低位
后面以此类推
注意注意注意(重要的事情说三遍):在程序编写完后,可能出现有些行未扫描,有些行的按键按下没有通过串口返回信息
我的解决方法是,在每一行的扫描之前,将行所对应的引脚清空
这样就不会有问题了
4、贴上完整程序:
#include "keypad.h"
#include "stdint.h"
#include "stm32f4xx_hal.h"
uint16_t Key_scan(void)
{
uint16_t Key_val = 0; // 按键扫描返回键值,初始化为0
// 强调一下: 这里必须付一个初值0 否则串口打印出错
uint16_t temp;
/*=========================以下代码是按键扫描程序=========================*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET); // 先清空引脚状态
/*----------------------------Scan the 1st ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET); // 设置PD0~2为1
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); // 设置PD3为0 二进制编码为 0111
if((GPIOD->IDR & 0xF0) != 0xF0)
{
HAL_Delay(10); // 10ms延时消抖
if((GPIOD->IDR & 0xF0) != 0xF0)
{
temp = (GPIOD->IDR & 0xF7); // GPIOD->IDR寄存器为端口输入数据寄存器
switch(temp) // 用来读取GPIO口的电平状态
{
case 0xE7 : Key_val = 1;
break;
case 0xD7 : Key_val = 2;
break;
case 0xB7 : Key_val = 3;
break;
case 0x77 : Key_val = 4;
break;
default : Key_val = 0; break;
}
}
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
/*----------------------------Scan the 2nd ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
if((GPIOD->IDR & 0xF0) != 0xF0)
{
HAL_Delay(10); // 10ms延时消抖
if((GPIOD->IDR & 0xF0) != 0xF0)
{
temp = (GPIOD->IDR & 0xFB);
switch(temp)
{
case 0xEB : Key_val = 5;
break;
case 0xDB : Key_val = 6;
break;
case 0xBB : Key_val = 7;
break;
case 0x7B : Key_val = 8;
break;
default : Key_val = 0; break;
}
}
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
/*----------------------------Scan the 3rd ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);
if((GPIOD->IDR & 0xF0) != 0xF0)
{
HAL_Delay(10); // 10ms延时消抖
if((GPIOD->IDR & 0xF0) != 0xF0)
{
temp = (GPIOD->IDR & 0xFD);
switch(temp)
{
case 0xED : Key_val = 9;
break;
case 0xDD : Key_val = 10;
break;
case 0xBD : Key_val = 11;
break;
case 0x7D : Key_val = 12;
break;
default : Key_val = 0; break;
}
}
}
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
/*----------------------------Scan the 4th ROW----------------------------*/
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET);
if((GPIOD->IDR & 0xF0) != 0xF0)
{
HAL_Delay(10); // 10ms延时消抖
if((GPIOD->IDR & 0xF0) != 0xF0)
{
temp = (GPIOD->IDR & 0xFE);
switch(temp)
{
case 0xEE : Key_val = 13;
break;
case 0xDE : Key_val = 14;
break;
case 0xBE : Key_val = 15;
break;
case 0X7E : Key_val = 16;
break;
default : Key_val = 0; break;
}
}
}
return Key_val;
}
5、 这是我的测试结果,见下图:

这个程序中的编码只是对应于我自己的接线,自己写的时候要注意自己的接线
史海拾趣
|
现在的汽车设计工程师正不断致力于设计出重量和能耗更低,同时安全性和舒适性更高的汽车。工程师们越来越排斥利用常规的能耗技术——笨重而高成本的机械解决方案来达到这样的目标。平均到每一辆车来说,每额外增加50kg的重量或100W的功率会带来0.2 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 1、今年不叫Sony杯了,好象换NEC赞助了。。呵呵 2、今年会对“最小系统”给出定义或者说明,所以往年的准备思路可能要换一换了,基本上现在给出的最小系统的概念是“单片机,ADC,DAC,存储”。一定 ...… 查看全部问答> |
|
在一个小系统中调试发现,如果在时钟初始化中里把AFIO打开,那么USART2就进入不了接收中断,关闭AFIO后,USART2接 ...… 查看全部问答> |
|
这不是一个单纯的 为论坛提出BUG什么的帖子。 这只是一个实践,一个关于测试的实践。 我很久没打开个人空间了,无意打开,发现了这个新功能。 叫 碎碎念一下 是个小问答。挺有爱的,我就试试咯 结果至今尚未成功过一次。 于是我想到,给这个小 ...… 查看全部问答> |
|
其实很弱,自己在模拟方面,大二学模拟电路的时候,听说了这个工具-- Multisim ,在之前使用过 proteus 软件做过51的仿真。其实自己当时也不知道 proteus和multisim的区别,只是听学长说proteus是用来做数字的,而multisim 是用来做模 ...… 查看全部问答> |
|
今天想用一下ubantu系统,所以在友晶官网上下载了ubantu系统,装上SD卡后启动什么的一切都正常,但是无法联网,我用的是宽带连接拨号上网方式,求原因 … 查看全部问答> |




