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

【零基础学习STM32】第二讲:GPIO输入实验——读取按键状态

[复制链接]
heart蓝色CD 发布时间:2018-1-27 13:11
接上篇:第一讲:GPIO输出实验——点亮三色LED
" O( F- S" U- [4 c: p* `
# V/ O1 Q. V$ _' ?# [, T一、概述
$ ~7 D( R  x' X' q0 W  i0 L1、按键简介
7 Z3 |; V! {& I+ V3 D" [      按键是一种机械器件,按键两端分别对应某电路的两个断点,我们可以通过按键接通和断开控制该电路的电压等参数,我们利用按键做的应用通常有控制继电器、键盘、复位等。随着应用的扩展,按键已成为电路板上不可或缺的一部分。% q: ?, Z9 G; K7 d4 p
如下图是常开按键:
2_0.png
2、按键类别简介
      按键主要有四种类型:常开带复位、常开不带复位、常闭带复位、常闭不带复位。(本次实验使用的是常开带复位按键)
按键主要有以下4种工作模式:
  • 常开带复位:初始默认状态是开路,当受力按下时按键使电路连通,受力结束后其自动返回开路状态。
  • 常开带不复位:初始默认状态是开路,每按下一次按键改变一次开闭状态。
  • 常闭带复位:初始默认状态是连通,当受力按下时按键使电路开路,受力结束后其自动返回连通状态。
  • 常闭不带复位:初始默认状态是连通,每按下一次按键改变一次开闭状态。
    * W6 I* X, p# z; T) G# O. D
3、按键消抖
1 [! |& x/ O8 o      使用手动按键的时候, 由于机械抖动可能造成按键的错误识别。一般手动按下按键然后释放, 按键两片金属膜接触的时间大约为50ms,按键松开到稳定的时间为5-10ms。因此,如果在首次检测到按键被按下后延时20ms 左右再次检测,即可确认是否真的有按键被按下,从而消除按键抖动造成的错误识别。本实验通过给于一定延时后再进行检测,从而有效的避免了按键抖动带来的误判。
3 u# l. M4 Y, F' }
+ ~9 I, [8 B" d* m! t( z二、硬件电路" C% C! L0 J1 d# c
2_1.png
" S8 h# _. ]  ]) Q7 ~# E 2_2.png 1 C2 @# F" J, h
% R, u" s: U6 s$ X1 N' O
在iCore3双核心开发板中,采用一个独立的按键与STM32F407的PH15相连,限流电阻为1K。

4 _* z. w: a. o4 A: L) \
三、实验原理
2_3.png
      按键的一端与STM32的GPIO(PH15)相连,另外一端接地,且PH15外接一个1K电流大小的上拉电阻。初始化时把PH15设置成输入模式,当按键弹起时,PH15由于上拉电阻的作用呈高电平(3.3V);当按键按下时,PH15直接被按键短接到GND,呈低电平。因此判断PH15的电平变化,可得到按键状态。

/ T$ A$ p- L$ _/ n+ y5 S9 `
四、源代码
1、主函数
  1. /*
      s  v( r1 ?( n3 p
  2. * Name                : main6 \# m+ ]# W0 z- u1 [) C, T
  3. * Description         : ---
    , H/ `4 ^+ G+ a% A; r
  4. * Author              : ysloveivy.
    8 @. W' n8 `" ]/ B
  5. *
    # `. w  V; o0 M! N" c* g
  6. * History" w8 j2 z9 x( P  s9 b/ i" `
  7. * --------------------
    ) v" E" F" E. a' y% D# @
  8. * Rev                 : 0.006 X3 G  C# ]& n4 K! g+ o7 A
  9. * Date                : 11/21/20157 K! `% v/ D1 n: x
  10. *
    5 a1 G2 {' k$ ?" s* {
  11. * create.
    5 Q/ S0 v1 F/ e* }
  12. * --------------------
    1 x( f% u6 C( L7 \: c
  13. */1 {5 U3 }7 T6 F! Y; D1 i  b
  14. int main(void). s/ H- K8 u1 l) u
  15. {
    ) |' A0 o6 K) A- l' d2 n- k
  16.         int i;+ B* o1 ]4 O' b" }
  17.         static int work_status = 0;                         //三色LED灯工作状态
    & c0 ?9 |; V! s) t
  18.         static int key_status = 1;                          //按键松开标置
    ; l% G* M! O' D1 O' d2 [% n! y
  19.         led.initialize();                                   //三色LED灯端口初始化3 `/ t( j4 y3 Y1 g8 w
  20.         key.initialize();       }8 Q% V6 l* ?. |9 t* S% A4 H
  21.         while(1){5 B8 b4 ~' }) |6 T
  22.                 if(KEY_INPUT)key_status = 1;
    # X/ c  I) P7 c! Q3 |) k# W5 c  S
  23.                 if(key_status == 1){: c1 s' S( i) _* l5 w6 P
  24.                         if(!KEY_INPUT){$ M2 k, n7 h* n8 A9 L
  25.                                 for(i = 0;i < 10000;i++);     //按键防抖动
    # P* Q7 Y" N. x* c
  26.                                 if(!KEY_INPUT){1 _+ M4 H$ b* K7 b
  27.                                         key_status = 0;4 L, ?% J% C4 D5 f
  28.                                         work_status += 1;$ M6 x) C! D4 p+ U
  29.                                         if(work_status > 2)work_status = 0;8 B: q  q+ r; r; o* Y3 E0 b
  30.                                         //操作 LED4 ?0 Q5 e+ r) o/ A
  31.                                         switch(work_status){' m) X9 L/ c+ k  `7 i6 s' D
  32.                                                 case 0:
    " ~: H3 g, P* V5 S( |2 k% _
  33.                                                         LED_RED_ON;
    ) n! O" }% i. N/ x3 A
  34.                                                         LED_GREEN_OFF;; z4 A0 b7 B' |8 J, |4 |9 v3 G
  35.                                                         LED_BLUE_OFF;; x8 t+ ?; I. Q% V
  36.                                                         break;% y3 p0 E3 o  b
  37.                                                 case 1:  {9 v/ \: S% o+ m; \9 V
  38.                                                         LED_RED_OFF;* ?  \# F, ^" ?. q$ N3 T0 J% A' v
  39.                                                         LED_GREEN_ON;
    - W+ m0 J& W. d8 y6 b' k( i3 T
  40.                                                         LED_BLUE_OFF;
    $ [  l  Q' X; w
  41.                                                         break;
    " p  ?" t- F/ o
  42.                                                 case 2:
    0 |) w9 n' a0 q) n0 f7 R1 H
  43.                                                         LED_RED_OFF;
    6 Z# V% |& p( Y/ C2 m; G: m
  44.                                                         LED_GREEN_OFF;" q$ U# n# P  o9 i1 ]
  45.                                                         LED_BLUE_ON;6 i' M9 o3 ?# i' |9 \4 J/ @" _; x# K
  46.                                                         break;: R  }5 ]0 d& Z5 C2 y3 L
  47.                                                 default:
    ' ~/ Z0 a7 e# F# T# R0 P# }. F
  48. * U$ @, V- Q+ E) {4 x) y/ i
  49.                                                         break;! u9 W8 \, Q5 u- i
  50.                                         }; u, m% o& P1 J; t. d
  51. ) M6 I; r2 r9 d' y0 j9 D
  52.                                 }1 W6 j; t* \9 v; b: y
  53.                         }
    6 K& Y; y/ I8 Z4 U
  54.                 }2 h3 `: K( ~* f; D' C
  55.         }% I; E7 O* U$ ]3 \$ f" {5 m
  56. }
    % f% l4 m$ _, g" j$ X. `7 B
复制代码
2、GPIO初始化
LED的GPIO初始化配置方式与上一讲一致,以下是按键的GPIO初始化程序
  1. /*% h3 b8 h; e- S/ C& l7 Q1 Z
  2. * Name                : initialize) p* x# C  @( f( q$ F+ m8 v: e4 o1 K' O
  3. * Description         : ---  H; W/ i) _/ F* |' Q
  4. * Author              : ysloveivy.4 @6 x$ O+ B; {+ w
  5. *
    * S- v8 V8 |1 T
  6. * History$ F; Q! d+ a' ]8 B
  7. * --------------------- g9 Q, \2 ]9 Q4 J9 g( g. }
  8. * Rev                 : 0.00  m6 X: ?( G( q& r# E$ w
  9. * Date                : 11/21/2015
    7 X. t4 y: F$ C. i
  10. * $ N# |8 p! p, a" o" d
  11. * create./ |. {& q) L, C3 n( g
  12. * --------------------
    : ^3 ], t7 p6 L& z( B# X9 o6 ]
  13. */$ I- h9 A: t  d# o
  14. static int initialize(void)
    . M! t0 h8 T# P& n% e( K
  15. {8 R1 g1 s3 h. V3 ^& t
  16.         GPIO_InitTypeDef   GPIO_uInitStructure;
    ) k/ S7 b! F$ z# }  i
  17. , r( y9 v' t' e% w# D* D0 y
  18.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);: D- L( l, ]+ [/ ~
  19.         //设置连接按键的IO端口
    7 ]2 m9 v6 Q- l! Y7 J( R6 }( O
  20.         GPIO_uInitStructure.GPIO_Pin = GPIO_Pin_15;                              w& {- {$ r5 O7 A
  21.         //设置端口为输入模式
    0 a4 T6 K3 l" q0 m' E$ u
  22.         GPIO_uInitStructure.GPIO_Mode = GPIO_Mode_IN;                          ! D6 P9 W' v9 v! D( L0 o
  23.         //设置速度为第三级
    / w/ g( [  E6 P4 D/ s% T. C. z
  24.         GPIO_uInitStructure.GPIO_Speed = GPIO_Speed_100MHz;                    - e; A4 b; `/ {5 A# J4 l
  25.         //设置输入端口不变化
    8 Z' {; B9 m3 O& C
  26.         GPIO_uInitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                     
    9 t* @- m+ A+ a
  27.         //把设置的参数用到结构体& i1 g, G9 v$ q4 A
  28.         GPIO_Init(GPIOH, &GPIO_uInitStructure);                                * {  q0 s- X/ i2 k2 l  r; o4 ?
  29. . z* Y( ~4 |) `  h
  30.         return 0;
    # V$ p1 }( U- @
  31. }
    - p( [- L. n) K2 l+ N
复制代码
3、小知识
void RCC_AHB1PeriphClockCmd
(uint32_t RCC_AHB1Periph,FunctionalState NewState)
此函数为外设使能函数,第一个参数为需要被使能的外设,第二个参数为使能与否。可能很多读者看到这函数不知道如何入手,不知道参数填啥子好,别急,咱先查看一下他的定义:

图2_4

图2_4
1 ~: T; O: @- ?5 }
查看定义方法:双击函数名选中,右击再点GO TODefinition of ...就可以查看咯。
RCC_AHB1PeriphClockCmd函数定义如下:
  1. void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState)
    / H9 V9 g5 _2 j# F$ \( Y. i0 E% b/ L
  2. {
    " q: _( H. {% J, c
  3.   /* Check the parameters */
    2 p8 s* D; z* o
  4.   assert_param(IS_RCC_AHB1_CLOCK_PERIPH(RCC_AHB1Periph));
    ! [/ b% b3 h. K/ ?4 N/ G
  5.   assert_param(IS_FUNCTIONAL_STATE(NewState));! I' p* o: b% a; d  r2 B# _
  6.   if (NewState != DISABLE)! X  |/ W9 X$ q1 ?1 ^" g: n5 J3 x  r
  7.   {# `5 ?5 }8 b. }' Y* |% R7 Q! A$ N# _
  8.     RCC->AHB1ENR |= RCC_AHB1Periph;, V* J8 L# L4 Q# A) t3 V8 y
  9.   }. [7 |  S  ~! t& z: K* |% I; r% n
  10.   else
    . C6 t) k" \5 M9 R4 |: ^
  11.   {0 ?) [% |+ Z2 V% l, {
  12.     RCC->AHB1ENR &= ~RCC_AHB1Periph;
    0 J- @, \7 |+ v% n
  13.   }
    1 O2 u5 Y' ~6 n) ~, R
  14. }
    2 D7 m7 |/ T3 X7 S3 _& q2 V% i: Z
复制代码

7 z8 B9 ?7 h4 n6 S+ V8 [3 ]* h2 o
注意被我标红的字符串,按照刚刚查定义的方法,它会告诉我们函数的参数可以填啥。如查看IS_FUNCTIONAL_STATE:
  1. #define IS_FUNCTIONAL_STATE(STATE)
    4 t+ m- z7 a1 v
  2. (((STATE) == DISABLE) || ((STATE) == ENABLE))
    " Z) H* g3 V: M2 c9 k8 f% G
复制代码
我们可以看出第二个参数可填写DISABLE(使能)和ENABLE(不使能)。

' _# t' w5 S7 O4 }) e0 R# E
小结:上面用外设的使能函数为大家介绍了查看函数的方法,此方法在实际应用经常可以用到,当我们在阅读、修改程序的时候,遇到哪些不太清楚的函数,就可以用这种方法查看。

, m5 d( Q' H: @
五、实验现象
按键每按下一次,ARM·LED颜色变换(红色、绿色、蓝色轮流交换)一次。

/ g6 c/ O" D7 s
六、代码包下载
复制网址到浏览器可下载pan.baidu.com/s/1sjrHnM9

7 Y9 B! z; {8 {* {4 L! v2 U& @8 O% \9 l! ?

, g, [, S8 M- x' Q
$ _+ W2 ]$ v) r3 o
7 F3 E$ O. p1 }6 ^

评分

参与人数 1 ST金币 +2 收起 理由
MrJiu + 2 赞一个!

查看全部评分

赞 收藏 评论4 发布时间:2018-1-27 13:11

举报

4个回答
Inc_brza 回答时间:2018-1-27 15:06:38
顶CD哥
努力的人 回答时间:2018-1-28 16:27:22
这个写的很详细,应该画了很多心思弄的,按键应该属于GPIO输入吧,你看看题目是不是改下
zero99 回答时间:2018-2-1 09:25:00
感谢支持,已汇总到1月技术原创0 F2 X0 u; L8 U+ t# p
https://www.stmcu.org.cn/module/forum/thread-614550-1-1.html
heart蓝色CD 回答时间:2018-2-2 14:10:29
zero99 发表于 2018-2-1 09:25
5 I% x" A$ O% ~4 `8 j感谢支持,已汇总到1月技术原创
4 n3 v7 `+ Y# qhttps://www.stmcu.org.cn/module/forum/thread-614550-1-1.html ...
9 F& n2 }% j+ m* g  J, _
感谢
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版