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

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

[复制链接]
STMCU-管管 发布时间:2021-6-7 17:43
基于STM32的按键扫描测试程序(学习记录):% P+ l& O+ `- \; f# k8 C% c; M9 Q

4 W9 f& n. ^. _" n* I3 I) i5 S8 ]

/ M7 v2 A" |: V6 L1、粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文字符;: W& ]( o# A: V9 @
2、程序使用嵌套循环实现4x4按键扫描,如果IO口设置过乱时,将循环拆分即可;
2 G# C; I& S5 ]  h/ l1 ekey4x4.h源文件
9 ~# Y: r% x* c. ~" ^
  1. #ifndef __KEY4x4_H! d6 [) e. v1 N0 q7 J
  2. #define __KEY4x4_H         
    2 V! a# T  P6 x: U" ]) }
  3. #include "sys.h". V+ j& f+ k1 \/ m5 i

  4. $ C3 c% K! o# t* y
  5. #define KEY_X(X)        PEin(X)                                // 尽量避免使用PD以上GPIO,便于移植;  e2 S# g5 a  l0 p. a! G
  6. #define KEY_Y(Y)        PEout(Y)
    0 w9 C: S: c, T' ]+ h1 M# \/ h" T9 p

  7. 5 ?% C# `6 x& H( T$ T, o
  8. #define ALL_DOWN_KEY_Y        {        KEY_Y(11) = 0; KEY_Y(12) = 0; KEY_Y(13) = 0; KEY_Y(14) = 0;}* G7 p' }* Y( d  _( R, d) o
  9. - G. R% p8 _. B+ [: L2 }
  10. void KEY4x4_Init(void);                // IO口初始化# K8 B4 K- N7 F( p9 Q9 S! c
  11. u8 KEY4x4_Scan(void);                  // 矩阵按键反馈函数        // 可配置任意矩阵按键使用!!
    0 G; V* Q% g, O; d! A' B  {
  12. u8 KEY16_Scan(void);
    3 k, {  \. ?2 p

  13. 6 }7 T4 ?! ^. A6 T8 l$ v
  14. /**************
    & i0 a0 [8 Z+ |
  15. 按键扫描方案二:3 g' T8 O  M( G- ^, O" p
  16. 按键使用8个输入IO口, 且所有IO口一端接VCC/VSS;
    # O6 n5 j3 ?6 l2 V5 g2 v

  17. ! x% a  ?" X' S. C+ {
  18. 程序框架:       
    * {) Z! f3 g- A, E) j9 A# q
  19.         扫描检测哪两个IO口输入高/低电平;VCC/VSS8 T, u) U. q2 I: H
  20.         根据对应坐标,return对应编号;
    $ O+ |! N, a$ \
  21. **************/; N# N( [8 i& ]# Y6 U- E1 x7 o- {% u- m

  22. : b, R7 C3 A7 C) ]; O
  23. #endif" H" G1 k3 W$ @- _1 U
复制代码
key4x4.c源文件
8 K, ]6 c5 m1 B
  1. #include "stm32f10x.h"+ |! s0 f: n+ Q
  2. #include "key4x4.h"
    . K9 d7 V" g) ?: G6 R* N3 |% s/ R
  3. #include "sys.h" # j( [. g  {6 Y3 `$ ~
  4. #include "delay.h"$ ~5 V! f' c) G% H* w- v
  5. #include "usart.h"$ ~; J6 a+ R* u. Q5 p' z
  6. 6 r0 }1 b( F9 _2 J2 Z
  7. ; L* `# \3 f8 h: [( h. S
  8. /*************************
    * g# e( B) m% L+ S7 A
  9. X:
    ) s6 F$ {- m1 U# @
  10.         PEin        7-10
    9 J& q7 M1 e/ {( T/ d( H
  11. Y:
    7 K* x) Y  z" h' P! [
  12.         PEout        11-14; ^- i) B8 [) v- a5 y' N- T
  13. *************************/0 W4 l7 c' M: I9 L; F. |

  14. ' L: U& N. Y5 W4 Y; o
  15. 3 |( u4 B* Y& z6 g
  16. // 矩阵按键初始化函数% O5 U" }* x' ?. {3 }
  17. void KEY4x4_Init(void)" l3 q- w0 Q4 C# b
  18. {
    4 n  B! b" C: n$ K# ?
  19.                 GPIO_InitTypeDef GPIO_InitStructure;
    * \2 c8 _$ F0 W; J  }) z
  20. ! ]8 _6 Q& o! ?$ v$ r
  21.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);. B* H# ?& D* A3 \# u6 e- K

  22. 1 Q  v3 U8 V( I# ]# |
  23.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//KEY0-KEY1
      S4 a, a7 E7 h7 h/ N. Q
  24.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成下拉输入
    / p* n* e; `  v5 w5 b# |
  25.                 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE
    ( q6 f- T0 r6 k- D& G
  26. 5 a5 a8 G5 G, }, f
  27.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;                                 //LED0-->PB.5 端口配置+ V! f+ J/ @- `
  28.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出* j& s$ s& B5 g$ U# p
  29.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
    " y: {$ k/ v$ a$ K' T- M+ C! M' z1 x
  30.                 GPIO_Init(GPIOE, &GPIO_InitStructure);                                                         //根据设定参数初始化GPIOE  L7 |" B/ Q4 ~/ d. X4 N
  31. }6 n5 e( _% V% t/ l% I
  32. ; b, y  ~# p* V5 N
  33. // 使所有输出拉低;初始化;                // 可以使用define宏定义,执行速度更快,不用跳转函数!!
    ( s* N5 T7 t- m2 ]
  34. static void KEY_ALL_Pull_Down(void)
    # r5 U: H- y9 q( I; g
  35. {
    ; I# a9 P# {  X
  36.         KEY_Y(11) = 0;
    6 d, c% D* A$ A" ?# ^7 v
  37.         KEY_Y(12) = 0;; w. L$ R/ V/ f, K6 _/ j7 w
  38.         KEY_Y(13) = 0;# f/ ~4 g& Q* U2 U( P. V& S
  39.         KEY_Y(14) = 0;! x3 P* ]- l) I; I, _. O$ a( l6 I
  40. }
    % j/ \5 O. s0 R& ?, i  g
  41. % u  U5 z) l5 h" r& c, k
  42. // 4x4按键扫描函数1 c/ Q! p2 h& z. H
  43. // 使用一个嵌套循环,完成扫描X和Y;3 L$ x4 L! r* o3 p6 I. I
  44. // 原理: 通过Y 依次输出高电平,6 p/ l7 \0 e  S0 Y& @4 Y6 l8 S
  45. //                                扫描X 那个IO口输入高电平;
    9 ], u* M0 r1 Q# U7 o
  46. // X轴:输入检查、扫描;
    : P1 e9 h( @+ K
  47. // Y轴:设置输出状态;' C9 v. L9 i# }5 ?/ q
  48. // 该函数适合任意排列矩阵按键,只需修改循环中对应编号!!! z9 B: Z, r  Q; b
  49. // 注意: 1. 改变IO口时,该函数还需要改变循环中IO口编号;(可以定义好IO口编号,便于修改)- W+ f( o6 Q9 |& L! G
  50. //                                2. 该函数同样有优先级问题! 即同时按下时,只反馈先被扫描到的(0-15标号最小的)
    ( x+ C) x  E0 h, n% E
  51. //                                3. 函数同一坐标轴的IO口编号必须相邻或能有 规律递增可寻;(否则无法用循环判断)
    2 O4 @, x! W3 J' b% c: y
  52. //                                4. 暂时未添加功能(模式):        按键复用 和 长按;: M+ Z% n# T  r( B( M1 K: g. J3 v
  53. // 2020-11-13                返回值调整为:1-16- D( K1 t& n& A/ i
  54. // 11/14 不支持连按;解决重复反馈的问题;
    + {5 `& S: Q) A/ k8 f& n
  55. u8 KEY4x4_Scan(void)
    $ `; d1 m0 r+ [
  56. {, K, }0 `! |5 s. g! }
  57.         int i,j;
      P* a. F6 Q: s
  58.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键# Z' B: c+ I' n
  59.         static key_up = 1;
    6 P# U5 c1 G! J# W8 H
  60.        
    / v  |7 _# z( T6 M  y
  61.         //KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低;& U0 h5 k; w# D# w4 G- R
  62.        
      N3 @* ?# y1 ~- d) b  D* \
  63.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;
    , {3 S9 i( N) |. i
  64.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
    & \( q: `: f5 L5 {$ d% k8 d$ d
  65.                 {; G  a( u/ W) ]
  66.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;
    . k6 v) `' ]3 |. d! f
  67.                        
    9 \' T$ G6 |7 R9 X
  68.                         if (KEY_Y(i))                        // 扫描Y输出高电平, 可以取消此判断; 因为必须输出高电平时,才能正常判断!!! F$ N! Y$ h$ _2 H2 G. k
  69.                         {
    : R) k# Z6 m% r: `. i4 h
  70.                                 if (KEY_X(j) && key_up)                // 当输入检查到高电平时;
    - j, ?  E- r! C# W/ j8 S0 \
  71.                                 {
    " B, p: B/ v  C- ~3 ^0 c! r  ~
  72.                                         key_up = 0;
    ' k7 c2 \* w5 I* j7 P$ Y
  73.                                         printf("按键扫描反馈: %d  \r\n",IO_Sign);  j  p* f6 y, O" v, V
  74.                                         return IO_Sign;& N4 Y) g/ t. Q# j0 S8 a# n
  75.                                 }
    9 f. Y- Z$ K( |
  76.                                 else if (!KEY_X(7)&&!KEY_X(8)&&!KEY_X(9)&&!KEY_X(10))                        // 当所有输入检测到低电平时,再次使能按键; 防止重复反馈
    7 Y1 _2 j  u9 ], y2 }% t
  77.                                 {5 L% N) S, K: T  M
  78.                                         key_up = 1;
    / [3 J  o! k- k+ A6 ?* p
  79.                                         KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低(低电平);必须在此位置;
    9 T7 A- \) C- ]' Q
  80.                                 }
    $ v6 S9 r& ?7 q( c8 `' @; n
  81.                         }( [# N! g0 T5 H% z7 }
  82.                         else
    5 O  n, T* \% b# P1 l8 ?3 Q
  83.                                 printf("PEout:IO口%d输出异常!  \r\n ", i);' I0 |8 a  N4 r
  84.                 }9 K$ H' z% C5 n2 S  X
  85.                 ) i3 h0 `' j8 h4 X* I; x$ F! j
  86.         delay_ms(10);                                        // 按键防抖;
    # Y: G! Z+ E, `" T
  87. }
    / \0 y9 u% ]8 l/ u6 W# _! z: l

  88. % {! B7 }4 q, L: Z* s- z
  89.   E& `  X) O8 F( C' y
  90. /******************************************标准扫描函数*********************************************/
    1 X: W" c( q# R3 ?* j2 A8 _
  91. // 支持连按9 P' z( c6 u( L0 Y/ D, B# d/ [; W
  92. u8 KEY16_Scan(void)
    6 o, d; ]3 @7 x" v8 W( z; g" A7 S: g
  93. {, z: j6 {+ z$ o/ T& _6 j
  94.         int i,j;
    5 u) X7 P+ l1 ]) y  t7 k3 V
  95.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
    " R2 H. M3 E+ |0 w3 f- u
  96.         3 Z( V5 i1 l1 I& f! M$ l3 p
  97.         ALL_DOWN_KEY_Y                                                                                                        // 初始化所有按键输出拉低;
    ' b! ?: U3 _" r; z" T2 k2 P
  98.        
    8 r2 m! @" I5 y# X/ h
  99.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;$ A, L) E0 v7 ^! {6 X
  100.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
    % }1 M* `: }- s: P: t
  101.                 {- R( c" k- W- {6 i
  102.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;
    ' [2 D" _5 Q% Q8 U4 S

  103. ; E& z" N) p9 X& y( Y5 S7 v) N9 L
  104.                         if (KEY_X(j))                        // 当输入检查到高电平时;. X: d+ d' v. t% o5 z* w% y* R
  105.                                 return IO_Sign;
    ) Y2 K0 h0 z3 d, ~" q' }+ ?( a
  106.                 }% j/ d$ ^! Q% b) @% V
  107.                 3 M2 ~6 M2 |. H- ^! f: T- P
  108.         delay_ms(20);                                        // 按键防抖;                // 连按延时;
    ) B' l' V7 ?3 ]
  109. }
    ' q, [3 D; }8 H! F% M

  110. $ B' H$ ~# A: H0 x! S* y+ U
复制代码
- ^4 l5 H2 k3 L7 v4 \6 _# z- b

" F! u% B4 M' R% k+ ^) f5 n*4x4按键原理图2 m- l8 X1 I& c7 l) Q( d
1.png
. a# S" [5 `( s, b: R# f# n3、按键工作原理:
) H1 j7 H% }$ F当按键被按下时,相连的电路导通;即S1按下时,位于0行0列的线短路,使标号4和5对应的IO口相连(导通);( t. v% c; c2 v; M# ^* O* W8 t6 _7 X
最后通过扫描检测输入输出状态即可判断出对应按键被按下;( b. z0 k3 m2 U$ E

* O7 g6 I) k2 k1 p' r: _: i3 Y

6 O9 }1 y5 K4 E- ]* v+ t; w4、程序设计思路:
( M1 f' }8 U5 z1 z程序通过依次使标号1、2、3、4(列0-3)输出高电平,判断5/6/7/8(行0-3)状态;完成按键扫描;
* S% p* \/ X$ t6 z6 x
% V! |7 K. w/ N0 U: z$ P' h/ j. e, z+ P1 a
) c/ t8 W8 F" Z" M- z& Q
4 X- ^4 M2 w. @; l7 R
收藏 评论0 发布时间:2021-6-7 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

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