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

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

[复制链接]
STMCU-管管 发布时间:2021-6-7 17:43
基于STM32的按键扫描测试程序(学习记录):4 q  N/ D# g; Q; K

+ m; _4 f1 N4 k, W7 v$ w
" F4 e$ g* Q" J+ W4 B
1、粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文字符;& Y3 q3 C, K: Y" J0 ]
2、程序使用嵌套循环实现4x4按键扫描,如果IO口设置过乱时,将循环拆分即可;
) ]0 O* b: z; \( Okey4x4.h源文件# i, o) Z# L6 w/ l
  1. #ifndef __KEY4x4_H& V6 k9 h$ ?7 c
  2. #define __KEY4x4_H         
    ; A' i. n- M6 \1 T
  3. #include "sys.h"
    / S' H6 L0 }; R
  4. ( S3 E* f( b& `2 d
  5. #define KEY_X(X)        PEin(X)                                // 尽量避免使用PD以上GPIO,便于移植;0 k3 R0 B. Q0 F; r* R
  6. #define KEY_Y(Y)        PEout(Y)1 Y- N: U; k& B3 j# [
  7. - _2 {' y" v2 v- B4 {
  8. #define ALL_DOWN_KEY_Y        {        KEY_Y(11) = 0; KEY_Y(12) = 0; KEY_Y(13) = 0; KEY_Y(14) = 0;}
      T6 p$ m8 q# @7 w, Z7 L

  9. ( y: G& O( p% n% Q; |
  10. void KEY4x4_Init(void);                // IO口初始化
    1 D+ ~; J! w/ ~: l! v
  11. u8 KEY4x4_Scan(void);                  // 矩阵按键反馈函数        // 可配置任意矩阵按键使用!!
    6 x' P: F/ X& L" z1 P- y7 ]
  12. u8 KEY16_Scan(void);8 g- d3 I( U5 P' ^# e4 H

  13. $ ?4 ]) x' g5 @
  14. /**************
    ; \8 Q; b. w( L1 o3 l3 j
  15. 按键扫描方案二:
    & d! u% z) R. _  O+ S5 u! i
  16. 按键使用8个输入IO口, 且所有IO口一端接VCC/VSS;: F9 L1 |4 n  F( y8 v
  17. ! I: i# {) Q2 {# d& C$ V
  18. 程序框架:        5 [' z9 \& G7 C4 c& v. W0 e* f
  19.         扫描检测哪两个IO口输入高/低电平;VCC/VSS$ c' F5 L. O  x& f. }7 ^
  20.         根据对应坐标,return对应编号;
    / q4 a, d+ N9 `8 T" ?' j( K
  21. **************/
    " g& ]7 X$ l$ v1 Y# T" N$ K
  22. % ?" g* ^5 T( ]3 F
  23. #endif% B3 k: C8 c) \5 S
复制代码
key4x4.c源文件3 J  g% i! {, ?3 ]
  1. #include "stm32f10x.h"* u  k; _( C  r- q: K
  2. #include "key4x4.h"; {( }0 p7 |1 g2 Z' @, o
  3. #include "sys.h"   @+ Q7 E0 |' S* `( ^2 K" l/ g
  4. #include "delay.h"
    ( {2 z+ G6 l3 a: b0 w# y0 [
  5. #include "usart.h"3 x* \* Y4 x2 d! p# u+ l& i5 K6 G/ `% j
  6. 0 x; t- r4 ?4 R* O+ l

  7. , i1 U  q2 ?0 [3 p
  8. /*************************6 v  ^2 q+ l5 g; d: j  f
  9. X:+ s9 t+ Z8 \; U1 _! V+ w
  10.         PEin        7-10; i( _8 F& a0 x) B1 H, T
  11. Y:
    5 n  R! X5 [. Z( ?
  12.         PEout        11-14
    : a/ I( ]3 ]" C9 w
  13. *************************/9 q. G( Q/ I' n# K5 |* M; K+ \! V
  14. 3 g' I, t  h5 H9 Z
  15. + N2 Y6 m- x8 {5 x* x& M
  16. // 矩阵按键初始化函数4 r, o3 y. C' n+ E2 i: S
  17. void KEY4x4_Init(void)
    9 R, k6 |" v" o
  18. {
    $ Y1 P' @! V6 |8 Y
  19.                 GPIO_InitTypeDef GPIO_InitStructure;
    ; p8 Z3 N: s4 C2 S, C' b, D$ n

  20. 8 F0 \: b/ h+ x5 J
  21.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);' [$ }8 }: V0 g7 V# G! F. x  @
  22. ! X" F2 k( h' Q4 o' g
  23.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//KEY0-KEY1
    - u& J/ e; K9 F; v) }. @
  24.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成下拉输入1 |1 D  y( x8 j$ x9 r( [, E; P
  25.                 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE
    - c. D8 a. D3 y; X/ d  F

  26. / _0 Q' |0 J5 A, D! c/ Q
  27.                 GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;                                 //LED0-->PB.5 端口配置# W+ y' K+ G7 S, v  b" X
  28.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
    0 `, |7 ~6 h" ]
  29.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz, R( L9 I  w0 Q) M* C+ E
  30.                 GPIO_Init(GPIOE, &GPIO_InitStructure);                                                         //根据设定参数初始化GPIOE3 a* `( j- m8 x( N8 m; L1 u
  31. }
    6 ^  B- [5 b3 [8 u& M: x
  32. 3 R% o: \, f; v, v5 E
  33. // 使所有输出拉低;初始化;                // 可以使用define宏定义,执行速度更快,不用跳转函数!!
    3 c! }( @; K/ w- p$ ]
  34. static void KEY_ALL_Pull_Down(void)  o, X  z- F* y8 c# m+ g
  35. {: w; I8 ^2 t9 |, P1 O: s
  36.         KEY_Y(11) = 0;8 k" L9 |- q$ N7 m9 v! [
  37.         KEY_Y(12) = 0;. N: }7 l" h6 Q  a% Q# P4 c
  38.         KEY_Y(13) = 0;
    ) ~3 v/ M+ \/ C3 h7 j% l" K
  39.         KEY_Y(14) = 0;
    " Z7 @- v. g# L7 S% Y2 o! x: t. v" E
  40. }+ Q- s% ?) E! |# u' M' |( O+ M

  41. 4 O$ G6 E! u6 g/ X# e' M; R
  42. // 4x4按键扫描函数# s7 i1 u& H% V( n) s2 {/ |' G: v: B
  43. // 使用一个嵌套循环,完成扫描X和Y;, \- q/ Q. h/ P
  44. // 原理: 通过Y 依次输出高电平,: O( }8 G" o+ n7 c0 W/ C1 n5 T  P! t% s* n
  45. //                                扫描X 那个IO口输入高电平;" V& p: y' n6 b- z: {. C8 \1 e
  46. // X轴:输入检查、扫描;
    / t: V9 q) {4 D3 Y! P- C
  47. // Y轴:设置输出状态;
    $ |  c6 B4 d- w2 F
  48. // 该函数适合任意排列矩阵按键,只需修改循环中对应编号!!
    ' M9 |" h& U- g+ x% g8 M
  49. // 注意: 1. 改变IO口时,该函数还需要改变循环中IO口编号;(可以定义好IO口编号,便于修改)0 u" F* J! l6 f  I7 O2 f* j
  50. //                                2. 该函数同样有优先级问题! 即同时按下时,只反馈先被扫描到的(0-15标号最小的)
    4 m* R! n5 |# `: h/ h3 Q8 v
  51. //                                3. 函数同一坐标轴的IO口编号必须相邻或能有 规律递增可寻;(否则无法用循环判断)
    % ?) \" ?; {2 [% i* o
  52. //                                4. 暂时未添加功能(模式):        按键复用 和 长按;
    7 [5 F# ?8 o0 L: ?+ E" w) C
  53. // 2020-11-13                返回值调整为:1-16
    . ^* z. U% u- o; \" C( R8 X3 U0 ?7 V
  54. // 11/14 不支持连按;解决重复反馈的问题;
    8 r6 g7 D( n# I  d! z, Z
  55. u8 KEY4x4_Scan(void)- r- y, u) d) @5 @6 @
  56. {/ O( C: ~2 v3 s1 U& U
  57.         int i,j;
    / e; b1 R# e8 J! y
  58.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
    , o* s" v0 R0 T4 n' r$ {) ?3 m
  59.         static key_up = 1;
    % A4 n4 y# J! N( r7 I, @
  60.         5 {* j# q* L  F& C
  61.         //KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低;; A% l8 A$ l& \9 V- |( t* ~. t
  62.        
    9 w4 m8 h6 l1 J1 e  p7 `( Q
  63.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;" c( x& h& I5 U5 a" c
  64.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);; c% d) [3 ]5 O  X
  65.                 {
    # m6 F& }; \, ^: p4 b9 a; ~2 [$ H9 w
  66.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;
    ; C9 j- V* f2 G
  67.                        
    # Q3 {" k! n. K2 ~1 |* @5 k
  68.                         if (KEY_Y(i))                        // 扫描Y输出高电平, 可以取消此判断; 因为必须输出高电平时,才能正常判断!!
    - l2 v9 s8 a' ~- c/ ]; e$ l  d# v
  69.                         {9 N6 y6 Q4 A+ Z8 P* n- t
  70.                                 if (KEY_X(j) && key_up)                // 当输入检查到高电平时;& B  V+ e& X  H: S
  71.                                 {1 D8 X! r6 t" \( a2 E" j( l( p- `: C
  72.                                         key_up = 0;+ d. F, [4 b: w! @6 K/ y7 ?$ \& c& k
  73.                                         printf("按键扫描反馈: %d  \r\n",IO_Sign);
    % {- V: K# _- r$ d2 {6 Y
  74.                                         return IO_Sign;; i6 B6 ~# o% n1 l; t5 I( n
  75.                                 }# y1 _6 u+ q) E
  76.                                 else if (!KEY_X(7)&&!KEY_X(8)&&!KEY_X(9)&&!KEY_X(10))                        // 当所有输入检测到低电平时,再次使能按键; 防止重复反馈
    " [2 p; {7 t0 W( ?
  77.                                 {
    7 e6 Y& F+ {9 y( J& C3 K* T* ?
  78.                                         key_up = 1;) ^) C# o; Y5 _4 ~( S% F. U& K* V
  79.                                         KEY_ALL_Pull_Down();                                                                                // 初始化所有按键输出拉低(低电平);必须在此位置;
    ( l8 Q3 M- u- f6 d" u
  80.                                 }0 `. f  m+ M1 B/ e- l
  81.                         }+ u5 p) t# f" w: ~% l2 _
  82.                         else
    1 I: q7 {0 }- n
  83.                                 printf("PEout:IO口%d输出异常!  \r\n ", i);
    6 n8 W' J' O  }( z
  84.                 }
    % A! z9 w0 Z5 [% |/ a9 m" }
  85.                
    : d0 Y( f# w8 w+ i$ s
  86.         delay_ms(10);                                        // 按键防抖;- M1 r# U% K: |: S& V6 A
  87. }- A% {$ t4 Q7 f  W1 r* L

  88. , y9 K1 q6 R" C9 u, H

  89. ) `2 I3 z8 _9 `) G8 `4 B: g
  90. /******************************************标准扫描函数*********************************************/
    1 y/ M6 u' y3 r% |; [: C
  91. // 支持连按
    9 k4 s3 h( x! Q& f: _. l
  92. u8 KEY16_Scan(void)% h. p) a9 A5 i5 B3 K8 [/ N
  93. {
    " x: X# g1 x4 C3 {: O
  94.         int i,j;
      r8 L% ?3 B# o. {0 Z$ J
  95.         u8 IO_Sign = 0;                                // 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
    ( |" j" a% T& N& L3 I' ^
  96.         8 V( r* R  F: A4 h2 x! L! G0 Q
  97.         ALL_DOWN_KEY_Y                                                                                                        // 初始化所有按键输出拉低;
    $ z( K, Q: T6 z7 X: C" I
  98.         & t+ `. W+ ]+ X. X
  99.         for (i = 11; i <= 14; i++)                                                        // Y输出IO口编号;
    , T0 |* N7 s/ N1 D7 p
  100.                 for (j = 7; j <= 10; j++,IO_Sign++)                // X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);) J( @3 L. d( P
  101.                 {* \" q2 W: l" W
  102.                         KEY_Y(i) = 1;                        // 使PEout(i)输出高电平;/ f) O# J( U8 B% d+ A( S

  103. * e! s* ^( M% _+ z" S! d& c
  104.                         if (KEY_X(j))                        // 当输入检查到高电平时;
    5 r2 ~; i9 y4 o8 ]# X, F8 p/ G
  105.                                 return IO_Sign;
    : s6 `' P; K+ g8 l% l* y9 I/ ~( C
  106.                 }
    ' @5 V/ Q  e- V' i
  107.                 ( R! U/ J7 s( N/ M) X: U3 I
  108.         delay_ms(20);                                        // 按键防抖;                // 连按延时;
    - z$ |- q7 P8 ?
  109. }
    0 U$ ?4 R6 F. ^" D' g
  110. 9 }$ w2 j8 x) e/ v
复制代码

$ A) v8 K9 I6 `( F

9 N- g5 `. e2 |8 z. d$ f2 M. C$ o*4x4按键原理图
+ U! e7 H% v# ~( V% D* s" o) G 1.png 5 ], a6 T) u2 v. g2 d
3、按键工作原理:* M1 z! z  D/ r/ A4 S
当按键被按下时,相连的电路导通;即S1按下时,位于0行0列的线短路,使标号4和5对应的IO口相连(导通);* V8 ]) T4 x& `3 k. \
最后通过扫描检测输入输出状态即可判断出对应按键被按下;
7 @9 c  U" r% U* r5 P
" ^! @% e  ]# K9 J. l/ _# ^
, e9 }7 b: g. [
4、程序设计思路:
( Q- I1 a! @2 e1 q6 |8 ~程序通过依次使标号1、2、3、4(列0-3)输出高电平,判断5/6/7/8(行0-3)状态;完成按键扫描;
1 P# B' f: w+ x. D! Q; c* l5 m$ I2 X  X* w$ n( x- m: s' f! c

$ t/ g0 A: ?* ^+ V
( I) j9 C# s! M
) d- T$ [" O$ D3 D  N( h
收藏 评论0 发布时间:2021-6-7 17:43

举报

0个回答

所属标签

相似分享

官网相关资源

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