历史上的今天
返回首页

历史上的今天

今天是: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、 这是我的测试结果,见下图:

在这里插入图片描述

这个程序中的编码只是对应于我自己的接线,自己写的时候要注意自己的接线


推荐阅读

史海拾趣

Frequency Electronics Inc公司的发展小趣事

为了进一步扩大市场份额,高频电子积极实施全球化战略。公司在全球范围内建立了销售网络和服务体系,与众多国际知名企业建立了长期合作关系。同时,高频电子还针对不同地区的市场需求,定制化开发符合当地标准的产品和服务。这些努力使得高频电子的产品和服务能够覆盖全球多个国家和地区,为公司带来了稳定的收入来源和持续增长的动力。

光大芯业公司的发展小趣事

在快速发展的过程中,光大芯业始终重视人才的培养和团队的建设。公司拥有一支来自国内外顶尖半导体设计公司的资深专家组成的核心技术团队,他们具备丰富的产品开发经验和创新理念。同时,公司还注重本地优秀设计人才的培养和引进,为公司的长远发展提供了坚实的人才保障。

Antenna Factor公司的发展小趣事

Antenna Factor公司始终注重产品质量和客户体验。他们建立了严格的质量管理体系,从原材料采购到产品生产的每一个环节都进行严格的把控。同时,公司还加强了对售后服务的管理和改进,确保客户在使用过程中能够得到及时、有效的支持。这些举措使得Antenna Factor公司的产品质量和品牌形象得到了显著提升。

ABCircuits公司的发展小趣事

ABCircuits公司成立之初,便专注于半导体技术的研发。在电子行业的浪潮中,公司敏锐地洞察到市场对高性能、低功耗芯片的需求,于是投入大量资源进行研发。经过数年的努力,ABCircuits成功推出了一款具有革命性的芯片,该芯片在性能上远超同行,同时功耗极低,迅速获得了市场的认可。这一技术创新为ABCircuits公司打开了新的市场领域,奠定了其在行业内的领先地位。

ELM Technology Corporation公司的发展小趣事

ELM Technology Corporation自创立之初,就致力于电子技术的研发与创新。公司聚集了一批顶尖的科研人才,不断探索新的电子技术和解决方案。在某一关键时期,ELM推出了一款具有革命性的电子产品,该产品在市场上引起了巨大反响,不仅极大地提升了用户体验,还推动了整个电子行业的发展。通过不断的技术创新,ELM逐渐在电子行业中树立了领先地位。

Greenconn Corp公司的发展小趣事
首先观察冰箱内灯是否亮起,如果灯不亮,可能是断电保护电路故障。此外,还可以使用万用表测量继电器和定时器是否工作正常,以及检查线路连接是否牢固。

问答坊 | AI 解惑

汽车控制单元和分立电子元件的重要性

现在的汽车设计工程师正不断致力于设计出重量和能耗更低,同时安全性和舒适性更高的汽车。工程师们越来越排斥利用常规的能耗技术——笨重而高成本的机械解决方案来达到这样的目标。平均到每一辆车来说,每额外增加50kg的重量或100W的功率会带来0.2 ...…

查看全部问答>

2009年电子设计竞赛的一些新特点~~

本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 1、今年不叫Sony杯了,好象换NEC赞助了。。呵呵 2、今年会对“最小系统”给出定义或者说明,所以往年的准备思路可能要换一换了,基本上现在给出的最小系统的概念是“单片机,ADC,DAC,存储”。一定 ...…

查看全部问答>

fpga资料大全

一些很有意思的fpga的开发资料,我也希望大家能多多指教…

查看全部问答>

STM32能接5V的器件吗,如MAX232?

                                  …

查看全部问答>

STM32103中关于AFIO和USART的问题!

                                 在一个小系统中调试发现,如果在时钟初始化中里把AFIO打开,那么USART2就进入不了接收中断,关闭AFIO后,USART2接 ...…

查看全部问答>

“TI杯”赛后交流群

大学快结束了,把自己的东西拿出来和大家分享一下,一起交流一下,未必不是一件快事。。。。 群名:“TI杯”赛后交流群 群号:130252614…

查看全部问答>

测试实践之 为 碎碎念问答 设计一个简单测试

这不是一个单纯的 为论坛提出BUG什么的帖子。 这只是一个实践,一个关于测试的实践。 我很久没打开个人空间了,无意打开,发现了这个新功能。 叫 碎碎念一下 是个小问答。挺有爱的,我就试试咯 结果至今尚未成功过一次。 于是我想到,给这个小 ...…

查看全部问答>

Multisim 作用有多大??

其实很弱,自己在模拟方面,大二学模拟电路的时候,听说了这个工具-- Multisim  ,在之前使用过 proteus 软件做过51的仿真。其实自己当时也不知道 proteus和multisim的区别,只是听学长说proteus是用来做数字的,而multisim 是用来做模 ...…

查看全部问答>

DE1-soc ubantu系统无法宽带连接拨号上网

今天想用一下ubantu系统,所以在友晶官网上下载了ubantu系统,装上SD卡后启动什么的一切都正常,但是无法联网,我用的是宽带连接拨号上网方式,求原因 …

查看全部问答>