你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103 矩阵键盘4*4 16*16等任意矩阵 按键扫描程序

[复制链接]
STMCU-管管 发布时间:2021-6-7 17:43
基于STM32的按键扫描测试程序(学习记录):


1、粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文字符;
2、程序使用嵌套循环实现4x4按键扫描,如果IO口设置过乱时,将循环拆分即可;
key4x4.h源文件
  1. #ifndef __KEY4x4_H
  2. #define __KEY4x4_H         
  3. #include "sys.h"

  4. #define KEY_X(X)        PEin(X)                                // 尽量避免使用PD以上GPIO,便于移植;
  5. #define KEY_Y(Y)        PEout(Y)

  6. #define ALL_DOWN_KEY_Y        {        KEY_Y(11) = 0; KEY_Y(12) = 0; KEY_Y(13) = 0; KEY_Y(14) = 0;}

  7. void KEY4x4_Init(void);                // IO口初始化
  8. u8 KEY4x4_Scan(void);                  // 矩阵按键反馈函数        // 可配置任意矩阵按键使用!!
  9. u8 KEY16_Scan(void);

  10. /**************
  11. 按键扫描方案二:
  12. 按键使用8个输入IO口, 且所有IO口一端接VCC/VSS;

  13. 程序框架:       
  14.         扫描检测哪两个IO口输入高/低电平;VCC/VSS
  15.         根据对应坐标,return对应编号;
  16. **************/

  17. #endif
复制代码
key4x4.c源文件
  1. #include "stm32f10x.h"
  2. #include "key4x4.h"
  3. #include "sys.h"
  4. #include "delay.h"
  5. #include "usart.h"


  6. /*************************
  7. X:
  8.         PEin        7-10
  9. Y:
  10.         PEout        11-14
  11. *************************/


  12. // 矩阵按键初始化函数
  13. void KEY4x4_Init(void)
  14. {
  15.                 GPIO_InitTypeDef GPIO_InitStructure;

  16.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);

  17.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//KEY0-KEY1
  18.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成下拉输入
  19.                 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE

  20.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;                                 //LED0-->PB.5 端口配置
  21.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  22.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
  23.                 GPIO_Init(GPIOE, &GPIO_InitStructure);                                                         //根据设定参数初始化GPIOE
  24. }

  25. // 使所有输出拉低;初始化;                // 可以使用define宏定义,执行速度更快,不用跳转函数!!
  26. static void KEY_ALL_Pull_Down(void)
  27. {
  28.         KEY_Y(11) = 0;
  29.         KEY_Y(12) = 0;
  30.         KEY_Y(13) = 0;
  31.         KEY_Y(14) = 0;
  32. }

  33. // 4x4按键扫描函数
  34. // 使用一个嵌套循环,完成扫描X和Y;
  35. // 原理: 通过Y 依次输出高电平,
  36. //                                扫描X 那个IO口输入高电平;
  37. // X轴:输入检查、扫描;
  38. // Y轴:设置输出状态;
  39. // 该函数适合任意排列矩阵按键,只需修改循环中对应编号!!
  40. // 注意: 1. 改变IO口时,该函数还需要改变循环中IO口编号;(可以定义好IO口编号,便于修改)
  41. //                                2. 该函数同样有优先级问题! 即同时按下时,只反馈先被扫描到的(0-15标号最小的)
  42. //                                3. 函数同一坐标轴的IO口编号必须相邻或能有 规律递增可寻;(否则无法用循环判断)
  43. //                                4. 暂时未添加功能(模式):        按键复用 和 长按;
  44. // 2020-11-13                返回值调整为:1-16
  45. // 11/14 不支持连按;解决重复反馈的问题;
  46. u8 KEY4x4_Scan(void)
  47. {
  48.         int i,j;
  49.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
  50.         static key_up = 1;
  51.        
  52.         //KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低;
  53.        
  54.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;
  55.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
  56.                 {
  57.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;
  58.                        
  59.                         if (KEY_Y(i))                        // 扫描Y输出高电平, 可以取消此判断; 因为必须输出高电平时,才能正常判断!!
  60.                         {
  61.                                 if (KEY_X(j) && key_up)                // 当输入检查到高电平时;
  62.                                 {
  63.                                         key_up = 0;
  64.                                         printf("按键扫描反馈: %d  \r\n",IO_Sign);
  65.                                         return IO_Sign;
  66.                                 }
  67.                                 else if (!KEY_X(7)&&!KEY_X(8)&&!KEY_X(9)&&!KEY_X(10))                        // 当所有输入检测到低电平时,再次使能按键; 防止重复反馈
  68.                                 {
  69.                                         key_up = 1;
  70.                                         KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低(低电平);必须在此位置;
  71.                                 }
  72.                         }
  73.                         else
  74.                                 printf("PEout:IO口%d输出异常!  \r\n ", i);
  75.                 }
  76.                
  77.         delay_ms(10);                                        // 按键防抖;
  78. }


  79. /******************************************标准扫描函数*********************************************/
  80. // 支持连按
  81. u8 KEY16_Scan(void)
  82. {
  83.         int i,j;
  84.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
  85.        
  86.         ALL_DOWN_KEY_Y                                                                                                        // 初始化所有按键输出拉低;
  87.        
  88.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;
  89.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
  90.                 {
  91.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;

  92.                         if (KEY_X(j))                        // 当输入检查到高电平时;
  93.                                 return IO_Sign;
  94.                 }
  95.                
  96.         delay_ms(20);                                        // 按键防抖;                // 连按延时;
  97. }

复制代码


*4x4按键原理图
1.png
3、按键工作原理:
当按键被按下时,相连的电路导通;即S1按下时,位于0行0列的线短路,使标号4和5对应的IO口相连(导通);
最后通过扫描检测输入输出状态即可判断出对应按键被按下;


4、程序设计思路:
程序通过依次使标号1、2、3、4(列0-3)输出高电平,判断5/6/7/8(行0-3)状态;完成按键扫描;




收藏 评论0 发布时间:2021-6-7 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版