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

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

[复制链接]
heart蓝色CD 发布时间:2018-1-27 13:11
接上篇:第一讲:GPIO输出实验——点亮三色LED0 u: [5 i+ N! v. E" o
; V* b  @: [1 J0 l
一、概述
* D: R  d: k0 c! G% Y1、按键简介+ j8 c" E' e0 r) _0 V! K5 Z) B
      按键是一种机械器件,按键两端分别对应某电路的两个断点,我们可以通过按键接通和断开控制该电路的电压等参数,我们利用按键做的应用通常有控制继电器、键盘、复位等。随着应用的扩展,按键已成为电路板上不可或缺的一部分。
: r9 o8 D) x& I5 }" |
如下图是常开按键:
2_0.png
2、按键类别简介
      按键主要有四种类型:常开带复位、常开不带复位、常闭带复位、常闭不带复位。(本次实验使用的是常开带复位按键)
按键主要有以下4种工作模式:
  • 常开带复位:初始默认状态是开路,当受力按下时按键使电路连通,受力结束后其自动返回开路状态。
  • 常开带不复位:初始默认状态是开路,每按下一次按键改变一次开闭状态。
  • 常闭带复位:初始默认状态是连通,当受力按下时按键使电路开路,受力结束后其自动返回连通状态。
  • 常闭不带复位:初始默认状态是连通,每按下一次按键改变一次开闭状态。1 e: i& c, |8 H! q; D
3、按键消抖
' y  c7 ~. |" m7 _+ C      使用手动按键的时候, 由于机械抖动可能造成按键的错误识别。一般手动按下按键然后释放, 按键两片金属膜接触的时间大约为50ms,按键松开到稳定的时间为5-10ms。因此,如果在首次检测到按键被按下后延时20ms 左右再次检测,即可确认是否真的有按键被按下,从而消除按键抖动造成的错误识别。本实验通过给于一定延时后再进行检测,从而有效的避免了按键抖动带来的误判。
) {$ M3 V5 ]% q
4 h& V. D( k7 `. D4 j1 @, q二、硬件电路$ {) {0 O( L; o& m6 @
2_1.png ; g6 F4 J( ]% N0 L0 Y
2_2.png
6 P3 B! z9 H1 ^& w
) S5 y+ d) E# ?- d6 O9 y
在iCore3双核心开发板中,采用一个独立的按键与STM32F407的PH15相连,限流电阻为1K。
& Z& T: B/ E5 X- ?
三、实验原理
2_3.png
      按键的一端与STM32GPIOPH15)相连,另外一端接地,且PH15外接一个1K电流大小的上拉电阻。初始化时把PH15设置成输入模式,当按键弹起时,PH15由于上拉电阻的作用呈高电平(3.3V);当按键按下时,PH15直接被按键短接到GND,呈低电平。因此判断PH15的电平变化,可得到按键状态。
3 K- W( g3 X1 C) M" y: T
四、源代码
1、主函数
  1. /*
    * I$ n6 l- u% w. u5 x3 N
  2. * Name                : main
    8 N8 x+ |0 g$ r; E: x9 ~( L- D9 G
  3. * Description         : ---
    0 D! S  x/ z! r2 h
  4. * Author              : ysloveivy.
      u; H, V- [+ J8 k5 U/ j3 c# e
  5. *
    8 X2 N* V& A$ k( N( d
  6. * History
    4 C5 f3 b! H6 K3 m- u! g
  7. * --------------------1 j8 v$ Y& K. F' H
  8. * Rev                 : 0.007 F' M6 t: a/ Y0 h1 q4 \& a
  9. * Date                : 11/21/2015
    / n+ R& c4 u: F* l: z+ C6 \
  10. * 4 I5 z0 w6 Q# G  J8 g3 Z
  11. * create.
    ! F! B# t3 J4 ]. j; q. Z2 C
  12. * --------------------
    ( h/ }- V8 L4 B2 S* u  h
  13. */9 F8 o' k, D$ p( B% I# A* v
  14. int main(void); W" |- O! `- r: N
  15. {
    ! I5 R$ l; G6 F* H" g3 ~0 D. q
  16.         int i;6 Z, s; m8 R9 D9 n( e* p
  17.         static int work_status = 0;                         //三色LED灯工作状态4 V% W, |( t& k# O* s5 t. D! `
  18.         static int key_status = 1;                          //按键松开标置
    * q) h1 V# M: N9 C5 q
  19.         led.initialize();                                   //三色LED灯端口初始化) j# L) P# v; T& p7 n
  20.         key.initialize();     
    / D4 n! h# e% L2 v
  21.         while(1){' t# K7 q+ @0 V
  22.                 if(KEY_INPUT)key_status = 1;$ k, {& G9 V/ Y" q9 \2 Y
  23.                 if(key_status == 1){
    . n& A# Y6 A, y" L: \" J
  24.                         if(!KEY_INPUT){" O  W5 J  ?: B+ _8 s
  25.                                 for(i = 0;i < 10000;i++);     //按键防抖动. E5 t  V# ~  c1 `, e; F
  26.                                 if(!KEY_INPUT){# c1 v5 e: v) Z/ o. @7 k
  27.                                         key_status = 0;
    7 b3 z- b2 ~6 B( s& g8 E) Q9 c+ C) S
  28.                                         work_status += 1;6 t7 z$ s- y) h8 N0 ~' U) ~
  29.                                         if(work_status > 2)work_status = 0;
    / v, U+ Q, o, W( {( b$ p! V" g
  30.                                         //操作 LED
    ( K1 ?1 n+ c+ z+ H2 {
  31.                                         switch(work_status){
    5 |+ G$ E( O  d8 X- J
  32.                                                 case 0:+ L% b2 j5 f0 C& H+ T7 o% H
  33.                                                         LED_RED_ON;
    0 j% [9 |( U! p0 K
  34.                                                         LED_GREEN_OFF;
    3 w! @$ N  M2 _+ R$ J; k, N
  35.                                                         LED_BLUE_OFF;
    & y6 H/ `& Q+ w5 Y/ }( x5 n
  36.                                                         break;
    & Y2 ^# y- ?( H6 V# z$ \) c/ Y
  37.                                                 case 1:: L8 N  e4 h0 {8 u
  38.                                                         LED_RED_OFF;- e8 |  a. P2 ~; ?
  39.                                                         LED_GREEN_ON;: g  S) N! R6 z, ~
  40.                                                         LED_BLUE_OFF;3 |( e( r$ k- d( e
  41.                                                         break;
    2 `& p; r( b. i2 ]3 V; B
  42.                                                 case 2:; m8 N1 w5 C) H; c6 O( |% h
  43.                                                         LED_RED_OFF;
    9 |# i1 ~% K- W1 l# A8 o- n, d; Z
  44.                                                         LED_GREEN_OFF;
    4 i7 q) l9 C$ s. ]2 @2 {
  45.                                                         LED_BLUE_ON;7 o5 [- Y( F: E7 ~
  46.                                                         break;, Q3 e; _' j! D; l. l( |
  47.                                                 default:
    0 c7 ^# i) D3 C, m( K6 T# y- l
  48. ! ?/ c9 @1 }' `% e* D: G
  49.                                                         break;
    - t5 K5 c% Q6 n
  50.                                         }
    " ^* W/ ?. `1 ?5 G/ A9 m
  51. 1 L! _* v) W7 Q$ U9 @
  52.                                 }
    * p3 Q0 p7 z: h+ G
  53.                         }
    ) @8 }6 W6 t% E2 D8 Y6 n' D, W/ q
  54.                 }
    * ]3 `( J: m/ K4 W) U4 r6 X
  55.         }" E' v! w4 y2 {. I* c: d+ r
  56. }
    0 n3 K) Y! O1 T  l4 q0 u! L
复制代码
2、GPIO初始化
LED的GPIO初始化配置方式与上一讲一致,以下是按键的GPIO初始化程序
  1. /*( g& j- V! z; }
  2. * Name                : initialize' F" s3 Z/ r& w0 w$ l$ q9 R
  3. * Description         : ---
    " \, w0 q9 y1 {
  4. * Author              : ysloveivy.
    ; E  T9 G) a3 C4 O3 K5 E
  5. *! w  j: ^# a  ?5 Z
  6. * History9 T( x; `5 a- g( Q# r: J# U8 b2 }
  7. * --------------------
    9 \+ l7 H% Q: A2 q. V% {
  8. * Rev                 : 0.00
    " B0 Y+ q3 }; o9 n
  9. * Date                : 11/21/2015" f* ~% I* F% j5 a' ^  C
  10. *
    ' k6 v( j# l$ t+ e; r' v) q( T+ ?& a
  11. * create.3 E; A$ w4 _3 |: ?4 q
  12. * --------------------" j+ G) A2 G. e5 N
  13. */& ^) R7 c- f/ }" E  B- b
  14. static int initialize(void)+ Z! D. \5 ~9 V: v% N5 G2 @
  15. {
    2 r+ c$ A" {/ L4 o
  16.         GPIO_InitTypeDef   GPIO_uInitStructure;
    ) ?; B: Q0 H7 l( g

  17. ! m5 U: Z8 c% X9 R
  18.         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);8 w& R' `! ~$ S( u4 O5 ?  c; _/ D
  19.         //设置连接按键的IO端口6 j3 ?6 l! y# }
  20.         GPIO_uInitStructure.GPIO_Pin = GPIO_Pin_15;                            ' d& H; t, [: U4 i0 q0 ~1 W8 U
  21.         //设置端口为输入模式( ?% p& Q0 ~* b$ M" X) X8 C4 Q
  22.         GPIO_uInitStructure.GPIO_Mode = GPIO_Mode_IN;                          ; J! b- G1 F! [5 C
  23.         //设置速度为第三级
    0 Y3 }! X0 N- z5 [& T9 y/ K& u, e
  24.         GPIO_uInitStructure.GPIO_Speed = GPIO_Speed_100MHz;                    ) K' |5 I: k- [7 y& t
  25.         //设置输入端口不变化
    9 J' f/ A9 z0 U$ A
  26.         GPIO_uInitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;                     
    : e  o/ }2 b" Y
  27.         //把设置的参数用到结构体
    1 q3 X6 Q( W" h( i. t! o# N; a* C
  28.         GPIO_Init(GPIOH, &GPIO_uInitStructure);                                " U/ ]# R1 M  M! Z& j6 b: d
  29. ; r; P' A9 `6 h; G$ b7 @3 G
  30.         return 0;
    8 Z: O, [3 n4 x
  31. }" ?/ u! J$ P3 |- Z5 s% ^
复制代码
3、小知识
void RCC_AHB1PeriphClockCmd
(uint32_t RCC_AHB1Periph,FunctionalState NewState)
此函数为外设使能函数,第一个参数为需要被使能的外设,第二个参数为使能与否。可能很多读者看到这函数不知道如何入手,不知道参数填啥子好,别急,咱先查看一下他的定义:

图2_4

图2_4
7 V" g) A' }/ \8 z% x
查看定义方法:双击函数名选中,右击再点GO TODefinition of ...就可以查看咯。
RCC_AHB1PeriphClockCmd函数定义如下:
  1. void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState)
    8 |6 S% @, V6 o: x, Z
  2. {
      y: h+ B( m  A  H. j
  3.   /* Check the parameters */8 Y% X; }$ M! N4 o$ v' W
  4.   assert_param(IS_RCC_AHB1_CLOCK_PERIPH(RCC_AHB1Periph));
    . [) a$ K: n0 N( _, o  |
  5.   assert_param(IS_FUNCTIONAL_STATE(NewState));- x$ D! q; b' }& N1 G" Z: @$ l: R; N
  6.   if (NewState != DISABLE)
      N% q1 v1 U' ^& p+ |. N( O+ @. ^
  7.   {
    0 S, t! A4 `' g. y
  8.     RCC->AHB1ENR |= RCC_AHB1Periph;
    4 Y6 t8 s/ {3 T
  9.   }  X8 c9 i, ^' P* D6 e1 o3 O9 l2 |& @
  10.   else
    & T$ I; `8 @  n
  11.   {$ W: I5 ^; |" ]7 T& Q1 E, m
  12.     RCC->AHB1ENR &= ~RCC_AHB1Periph;
    7 W% W) G  X: D7 {& C
  13.   }; w7 ^7 Q; R8 C/ R( O' E9 c0 `
  14. }
    : {% e8 U* l9 ]+ U! `
复制代码

9 z; V! w7 U! Q( P: R( F4 t6 X
注意被我标红的字符串,按照刚刚查定义的方法,它会告诉我们函数的参数可以填啥。如查看IS_FUNCTIONAL_STATE:
  1. #define IS_FUNCTIONAL_STATE(STATE)
    6 c* e' }: Z1 H6 C7 h9 O: O
  2. (((STATE) == DISABLE) || ((STATE) == ENABLE))
    : h, P3 @, |5 S6 V
复制代码
我们可以看出第二个参数可填写DISABLE(使能)和ENABLE(不使能)。
& w8 d' S/ _4 j2 }4 [
小结:上面用外设的使能函数为大家介绍了查看函数的方法,此方法在实际应用经常可以用到,当我们在阅读、修改程序的时候,遇到哪些不太清楚的函数,就可以用这种方法查看。
9 H5 K+ i# z& H1 S. s& a, K0 r2 r( G
五、实验现象
按键每按下一次,ARM·LED颜色变换(红色、绿色、蓝色轮流交换)一次。
! b( M0 {" p  O$ W. z. [( ^6 ^# I- [, C
六、代码包下载
复制网址到浏览器可下载pan.baidu.com/s/1sjrHnM9
! l( W9 b% K9 s' F  t0 k' H

5 w8 h0 s/ v1 J9 }5 |
8 P/ ?; ]. `* A8 r9 ~% h( N% J( O0 [( g

) M6 W% V+ o' E7 ~, T

评分

参与人数 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月技术原创! M7 q6 M7 t4 s2 P- i% O. Q
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( q9 P  m( j: u9 J: n
感谢支持,已汇总到1月技术原创
' o2 N2 L# [) R7 G& e, vhttps://www.stmcu.org.cn/module/forum/thread-614550-1-1.html ...
6 x% l, e, W% H9 A( Y
感谢

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版