找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4149|回复: 1
打印 上一主题 下一主题
收起左侧

STM32F407使用4*4矩阵键盘

[复制链接]
跳转到指定楼层
楼主
ID:350579 发表于 2019-3-7 16:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


# 基于STM32 使用 4*4 矩阵键盘

******************************************************************************



作者:李剀 出处:https://www.cnblogs.com/kevin-nancy/  或者  https://blog.csdn.net/Kevin_8_Lee/article/details/88084516
欢迎转载,但也请保留上面这段声明。谢谢!(上面这个也是我写的博客,只是在另一个平台)今天发布到51hei上面,

写在前面: 这是本人第一次开始写博客,可能写的不是很好,也请大家谅解。
                   本人现在大三,以前在学习过程中遇到过各种各样的问题,关于51单片机,STM32单片机,最近在学习ARM11的Tiny6410
                   以后还会更新一些C/C++方面的东西
                  关于写博客这件事,其实 一直想写博客记录下来,但是因为某些原因(懒),so , 没有写。现在开始,以后遇到单片机上或者编程上遇到的问题,
                  并且自己很好地解决了,我就会在这里记录下来。
                  希望通过博客记录我的学习历程并希望我所解决问题的过程能够帮到需要的人,一起加油吧!!!

我是在STM32F407开发板上使用的4*4 矩阵键盘
下面是我所使用的开发板

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)


![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)
1、首先介绍一下4*4矩阵键盘扫描原理

     呃。。。。。就不介绍了,[矩阵键盘原理描述](http://www.51hei.com/mcu/3815.html),这个写的挺好的

2、Cube配置

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)

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

![键盘原理示意](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)

        PD0-3依次对应3-0行  PD4-7依次对应0-3列   这张图里可以看到我画了两个箭头,下面就给大家说一下我的配置

        配置PD0~3为推挽输出   PD4~7为下拉输入,下图是我在STM32CubeMX 5.1.0中配置的

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)

        上面的箭头,横向的表示是单片机输出给键盘的,竖向的是表示送给单片机的,也就是单片机配置的输入引脚
        用来读取PD4~7的电平

3、程序编写

     因为PD4~7为上拉输入,所以是处在一种高阻态(可以暂时理解为高电平,就是四列都为1)
     我以扫描第一行为例讲解  ,

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)


![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)

        上述是软件实现部分, GPIO->IDR和0xf7相与, 若是0xe7  则二进制位1110 0111,说明PD4变为了0,所以第一列的按键
        s1按下
note:PD7对应二进制的最高位,PD0对应二进制的最低位

        后面以此类推
注意注意注意(重要的事情说三遍):在程序编写完后,可能出现有些行未扫描,有些行的按键按下没有通过串口返回信息
                         我的解决方法是,在每一行的扫描之前,将行所对应的引脚清空

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)
                            这样就不会有问题了


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

![在这里插入图片描述](?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0tldmluXzhfTGVl,size_16,color_FFFFFF,t_70)


这个程序中的编码只是对应于我自己的接线,自己写的时候要注意自己的接线
上面有些连接是我上传的图片,我自己看的时候看不到图片,不知道什么原因,但是点击链接打开就是图片了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

let‘s dream high   每个不满意的现在,都有一个不努力的曾经。加油吧


评分

参与人数 2黑币 +106 收起 理由
BigWheels + 6 赞一个!
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:558624 发表于 2019-7-27 19:28 | 只看该作者
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表