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

【经验分享】STM32G4之按键实验

[复制链接]
STMCU小助手 发布时间:2022-7-6 14:41
一、按键原理
5 i& _) ?$ C1 f- h; |( n4 o# e按键电路原理图(CT117E-M4产品手册)
( E7 S: i4 a% ^& u7 Q# j IY3%$NND62HF$%W1}CG6`WF.png
, M- _1 G, Z: P$ b: g- U1 ~
! l5 l& }' V5 U这四个按键一端都接了VDD,所以默认高电平,当我们按下按键时,电路闭合,IO口电平从高电平到低电平,检测IO口电平的变化就是判断按键是否按下的依据。9 Y9 R: x8 V  J) g$ K4 T& p
4 l* K; ?+ l7 A4 p
由于按键默认上电为高电平,所以可以选择浮空输入模式,该模式只是默认输入值不能确定,但是这里是接的VDD,也就是默认输入值高电平。而上下拉输入模式,默认输入值是确定的。读取输入结果时,只有0或1两种,只是默认值不能确定- R* ^# @8 k3 i0 Q4 ]# n$ s8 S
! ?3 ]- _7 K( I
在单纯作为输入的时,浮空模式是有用的,在外部有上拉/下拉的条件下,可以设置为浮空输入。或者IO有冲突的时候,也可以设置为浮空输入,从而完全不干扰其他IO; W7 L2 X9 T+ p: p0 P/ o) y

! ~; o/ v8 d& [9 t4 Y. K+ ~对比一下正点原子F4按键实验模式选择:KEY0,1,2选择的是输入上拉,KEY_UP选择的输入下拉: P& Z8 e* @  K8 n: ^

0 N/ [) R5 {$ y5 H) k Y4Z2P8(AUI1F8X)1C_5BK.png
- ?% I0 M' ~, r& ^, v0 F8 |) u
' H% Z# A* ]) {1 Z) G9 ^5 VKEY0、 KEY1 和 KEY2 是低电平有效的,而 KEY_UP 是高电平有效4 [, H+ U( v9 P& Z# A
的, 并且外部都没有上下拉电阻,所以,需要在 STM32F4 内部设置上下拉,STM32G4是可以看到外部接了上拉电阻的,所以程序里面没有设置上下拉模式9 c* r, C9 p6 N2 |) P! }

- t5 B' Q. _8 ?9 U- \输入上拉:无论输入管脚悬空或者被高电平驱动时,读取的都是1. 只有在输入端为0的时,读取到的值才是0。
0 I9 F3 E* ~" n& I/ u) P$ p) G3 q: |/ l: h0 o+ M
要判断KEY0,1,2的IO口电平,只有按键按下了,输入端为0 ,才能检测读取到低电平,所以这三个引脚选择输入上拉模式
# O6 x( g' W" G: |" H; Z
! B( ]; L% L: F9 R4 _输入下拉:无论输入管脚悬空或者被低电平驱动时,读取的都是0. 只有在输入端为1的时,读取到的值才是1。
9 c6 F. g4 X' m* U# S6 u/ B& l( Q! |2 b) R9 [" d% e3 ^/ b
要判断KEY_UP的IO口电平,只有按键按下了,输入端为1,才能检测读取到高电平,所以这这个引脚选择输入下拉模式  D9 H7 A! a& @2 h

3 L8 n: Z$ e: @$ kGPIO模式详细介绍:GPIO模式8 i, T5 v) S7 \: n5 s

) ]! F) V. b6 e& ]5 V' p1 H- C二、程序编写
, f0 T/ H8 [# `: }# t% T) W按键GPIO设置为浮空输入,使用STM32CubeMX配置2 p5 S( j" v0 C3 p9 ^' m
( r$ ~( ]8 z- N: @
D(N1_@FJ1KPTBMPZG7(1_7R.png ( j' @. I+ Q/ ~5 \+ Y* S/ U

& O6 D: [' X- [$ y3 K将里面按键IO的初始化移植到LED的工程下。
! D, n1 N# Q. f6 ]3 A/ F3 ]; [& t
) e4 R+ k' g1 {# R9 |- v) {  H9 I* v1.按键扫描函数
0 n# I. x' W) }
  1. unsigned char Key_Scan(void)4 {3 f: x# h8 m) ]: q1 o
  2. {# I1 g# a3 l/ Q  z) T2 t. \) \
  3.         unsigned char unKey_Val = 0;) T! [4 y' s' \" M7 G
  4.         ! n/ K& y. d4 c0 w0 `
  5.         if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET); s; W& g( d0 C" l
  6.                 unKey_Val = 1;- H7 T; {8 e! }7 G
  7. 9 ]$ L! W8 g$ B- L
  8.         if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET)
    + b/ M! |  v, O3 l8 v
  9.                 unKey_Val = 2;/ s/ R/ U; \* \$ [. {5 Z- T

  10. + f: q7 q: D  v! c" D% d. Q4 A
  11.         if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
    - E9 P( u& l, U( X+ }
  12.                 unKey_Val = 3;1 _: {1 c% w8 J; z$ C, Y) K; M+ P
  13.         4 E* J! N$ r0 [
  14.         if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
    8 \9 r+ z: A1 Q# M& |
  15.                 unKey_Val = 4;        
    ' q" G" i  e& L: O# z
  16.         / P8 t* t, f& ]& E& v( E3 X
  17.         return unKey_Val;" ~4 F# A. x" ?+ L# ?
  18. }
复制代码
$ B. Z. |3 t' o) }
2.按键处理函数8 f5 v5 G. z: ]/ ^" N

: H! ]* T% H: k1 x/ ~
  1. __IO uint32_t uwTick_Set_Point = 0;
    6 \4 ~. }$ g7 C; Q1 ^2 I; v

  2. # r7 k. x: |9 e- _  f
  3. unsigned char ucKey_Val,ucKey_Down,ucKey_Up,ucKey_Old;6 w) M2 D0 H( k% G" }/ X
  4. void Key_Proc(void)9 E  B4 }( Q& S3 V& [8 I
  5. {- `& Z/ w; I5 b# M1 s
  6.         // uwTick每隔1ms加1  刚开始肯定差值大于100ms
    1 B5 g9 ]2 h& s, i1 U
  7.         if((uwTick -uwTick_Set_Point) < 100) return; // 每隔100ms扫描一次        * n+ n% p0 Z' g' d- X  A7 ?2 r
  8.         uwTick_Set_Point = uwTick;  // 记录每次扫描时的uwTick值5 H. G& w9 U0 m' u
  9.         ; y0 Z8 \( S2 q5 G
  10.         ucKey_Val = Key_Scan();
    " b' `' s5 \! S
  11.         ucKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val);* Q4 r) \9 A4 n  Q% a8 ^# G: F
  12.         ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val);
    - G; i+ f- ]+ E0 c: l
  13.         ucKey_Old = ucKey_Val;
    / T1 N- h% u# p" U; G8 L
  14.         
    4 E0 U% n/ ^3 @+ Z  @& b( R+ K
  15.         if(ucKey_Down == 4)( m# z" U# C- F9 L* l
  16.         {' B$ F( C0 b5 V; U( n8 ~3 H6 f3 ?
  17.                 LED_Display(0x88);
    $ F; S3 k$ F8 w6 B+ x
  18.         }2 f. Q. a( \& E7 c; ~9 I, M
  19.         if(ucKey_Down == 1): h8 @* B+ t" J% N( \+ r
  20.         {
    % o* G8 @8 |( n7 x. X4 v
  21.                 LED_Display(0x00);, Y0 w# j$ @) h, Z) z
  22.         }% {1 P+ ?/ d: n" M9 R$ |
  23. }
复制代码
  1. &(按位与): 两个操作数都为1 ,才为1  1&0 = 0 0&1 = 0 1&1 = 15 s- H& \+ K1 D0 I
  2. |(按位或):两个操作数只要有一个为1 ,结果为1  1|0 = 1 1|1= 1  0|0 = 0
    ( B- q& D; u6 u; |4 A
  3. ^(按位异或):两个操作数相同为0 ,不同才为1 0^0 = 1 1^0 = 0# g4 t+ `% C- `
  4. ~(取反):0变为1 ,1变为 0 ~0=1
复制代码

. f( M5 t; k! h位运算参考:位运算, S; V" ~+ l8 l. a
) e% c4 y. {! V
按键扫描可以分为三种情况:
. l+ T4 x8 v) A8 [  n4 x
, z4 k$ e8 i$ |% _9 I+ ]
  1. 情况1 : 100ms扫描了两次,按键返回的结果从0 变为4(按键4被按下了),产生了下降沿9 ?( O; S. J5 f6 A* y9 j
  2. ucKey_Val = 4 (0000 0100)
    & D4 ^- ?- g$ K4 i
  3. ucKey_Down = 0000 0100 & (0000 0000 ^ 0000 0100) = 0000 0100 & 0000 0100 = 0000 0100 =41 {! a& ?! |! V# \
  4. ucKey_Up = ~0000 0100 & (0000 0000 ^ 0000 0100) = 1111 1011 & 0000 0100 = 0
    ) U, q) s2 `7 ^2 p! G* C
  5. ucKey_Old = 4
    6 F! V7 t# ?' f" m
  6. 8 K. B! P5 a, T+ H6 P- n( t
  7. 情况2 : B4产生了下降沿后,按键一直按着' Z  }/ a. _* U& q/ B- |1 N- x
  8. ucKey_Val = 40 ]  {2 W5 u# W* m& M
  9. ucKey_Down = 0000 0100 & (0000 0100 ^ 0000 0100) = 0000 0100 & 0000 = 0
    4 w: L2 [1 c, ~( g: h3 O
  10. ucKey_Up = 1111 1011 & 0000 0000 =0
    8 O/ |* X" ]- Z2 B3 P+ t1 \; R
  11. ucKey_Old = 0000 0100 = 4% ?) N8 m1 y0 @+ Q6 @# U" p" R
  12. 9 m5 I" e7 B% o
  13. 情况3 : B4按键一直按下后在松手时产生上升沿这个时候
    ( K  d: J2 W8 K2 A' E0 H
  14. ucKey_Val = 0+ g4 \/ M) ]9 a
  15. ucKey_Down = 0000 0000 & (0000 0100 ^ 0000 0000) = 0000 0000 & 0000 01000 = 0
    8 V; k  T; g9 u4 s4 C
  16. ucKey_Up = 1111 1111 & 0000 01000 = 0000 01000 = 43 x  z3 f/ u& t2 a
  17. ucKey_Old = 0
复制代码

- k6 D0 C- {7 k0 P' f/ }: o/ {, l5 a% g+ t4 v4 b# t

. I" `  b$ _6 J
# |7 u+ t9 h) ~5 e. m1 }- X
赞 收藏 评论0 发布时间:2022-7-6 14:41

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版