经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 计算机硬件 » 查看文章
STM32使用4*4矩阵键盘
来源:cnblogs  作者:K35inL  时间:2019/3/4 8:46:55  对本文有异议

作者:李剀 出处:https://www.cnblogs.com/kevin-nancy/
欢迎转载,但也请保留上面这段声明。谢谢!

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

我使用的是STM32F407zg的最小系统板

1、首先介绍一下4*4矩阵键盘扫描原理

  1. 呃。。。。。就不介绍了,http://www.51hei.com/mcu/3815.html,这个写的挺好的

2、Cube配置

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

  1. PD0-3依次对应3-0 PD4-7依次对应0-3 这张图里可以看到我画了两个箭头,下面就给大家说一下我的配置
  2. 配置PD0~3为推挽输出 PD4~7为下拉输入,下图是我在STM32CubeMX 5.1.0中配置的

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

3、程序编写

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

  1. 上述是软件实现部分, GPIO->IDR0xf7相与, 若是0xe7 则二进制位1110 0111,说明PD4变为了0,所以第一列的按键
  2. s1按下

note:PD7对应二进制数中的最高位 PD0对应最低位

  1. 后面以此类推

注意注意注意:在程序编写完后,可能出现有些行未扫描,有些行的按键按下没有通过串口返回信息
我的解决方法是,在每一行的扫描之前,将行所对应的引脚清空

  1. 这样就不会有问题了

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;

  1. /*=========================以下代码是按键扫描程序=========================*/
  2. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET); // 先清空引脚状态
  3. /*----------------------------Scan the 1st ROW----------------------------*/
  4. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET); // 设置PD0~2为1
  5. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); // 设置PD3为0 二进制编码为 0111
  6. if((GPIOD->IDR & 0xF0) != 0xF0)
  7. {
  8. HAL_Delay(10); // 10ms延时消抖
  9. if((GPIOD->IDR & 0xF0) != 0xF0)
  10. {
  11. temp = (GPIOD->IDR & 0xF7); // GPIOD->IDR寄存器为端口输入数据寄存器
  12. switch(temp) // 用来读取GPIO口的电平状态
  13. {
  14. case 0xE7 : Key_val = 1;
  15. break;
  16. case 0xD7 : Key_val = 2;
  17. break;
  18. case 0xB7 : Key_val = 3;
  19. break;
  20. case 0x77 : Key_val = 4;
  21. break;
  22. default : Key_val = 0; break;
  23. }
  24. }
  25. }
  26. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
  27. /*----------------------------Scan the 2nd ROW----------------------------*/
  28. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_3, GPIO_PIN_SET);
  29. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
  30. if((GPIOD->IDR & 0xF0) != 0xF0)
  31. {
  32. HAL_Delay(10); // 10ms延时消抖
  33. if((GPIOD->IDR & 0xF0) != 0xF0)
  34. {
  35. temp = (GPIOD->IDR & 0xFB);
  36. switch(temp)
  37. {
  38. case 0xEB : Key_val = 5;
  39. break;
  40. case 0xDB : Key_val = 6;
  41. break;
  42. case 0xBB : Key_val = 7;
  43. break;
  44. case 0x7B : Key_val = 8;
  45. break;
  46. default : Key_val = 0; break;
  47. }
  48. }
  49. }
  50. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
  51. /*----------------------------Scan the 3rd ROW----------------------------*/
  52. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);
  53. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);
  54. if((GPIOD->IDR & 0xF0) != 0xF0)
  55. {
  56. HAL_Delay(10); // 10ms延时消抖
  57. if((GPIOD->IDR & 0xF0) != 0xF0)
  58. {
  59. temp = (GPIOD->IDR & 0xFD);
  60. switch(temp)
  61. {
  62. case 0xED : Key_val = 9;
  63. break;
  64. case 0xDD : Key_val = 10;
  65. break;
  66. case 0xBD : Key_val = 11;
  67. break;
  68. case 0x7D : Key_val = 12;
  69. break;
  70. default : Key_val = 0; break;
  71. }
  72. }
  73. }
  74. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
  75. /*----------------------------Scan the 4th ROW----------------------------*/
  76. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);
  77. HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET);
  78. if((GPIOD->IDR & 0xF0) != 0xF0)
  79. {
  80. HAL_Delay(10); // 10ms延时消抖
  81. if((GPIOD->IDR & 0xF0) != 0xF0)
  82. {
  83. temp = (GPIOD->IDR & 0xFE);
  84. switch(temp)
  85. {
  86. case 0xEE : Key_val = 13;
  87. break;
  88. case 0xDE : Key_val = 14;
  89. break;
  90. case 0xBE : Key_val = 15;
  91. break;
  92. case 0X7E : Key_val = 16;
  93. break;
  94. default : Key_val = 0; break;
  95. }
  96. }
  97. }
  98. return Key_val;

}

5、 这是我的测试结果,见下图:

  1. ![](https://img2018.cnblogs.com/blog/1617398/201903/1617398-20190302200530024-2065140774.png)

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

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

原文链接:http://www.cnblogs.com/kevin-nancy/p/10462635.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号