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

STM32蜂鸣器/按键实验经验分享

[复制链接]
STMCU小助手 发布时间:2023-3-10 10:39
前言: J8 p. Y; [# p( V
使用的是芯片:STM32F407ZGTx  K* b$ q4 X2 P( q9 G
, I" x$ e, d, k9 V! l
学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。3 W  ~6 L0 h, V' t4 P2 b' E

% i2 L8 j0 m0 W3 t本文档添加了对代码的在线调试功能,有助于大家更好理解相关寄存器的变化。
( V8 S' H0 c* V3 ]8 l1 E  U& G) K) w( h
6 |" Z* D& @: H- Q; i$ k9 N& V' i/ `
理论学习
5 ^! ~- `: t0 Q8 j: ]4 ^0 _: b一、蜂鸣器简介

/ `/ ?4 ?5 f  w有源蜂鸣器自带了震荡电路 ,只需要对其上电即发声;无源蜂鸣器需要提供相应的方波才发声。  m: A2 Z7 Y" R) m/ f) V1 Q) |, z- F1 X
- r4 Z7 @( ]9 A
0ac2fea7841f448b8eeade067bc9cce0.png
8 e( s* ~2 i, A7 Z: X  v  @7 Y. A: U# b
32的IO口可以直接驱动LED灯(所需电流较小)。STM32F4的单个IO可以提供25mA电流,而蜂鸣器的驱动电流为30mA左右,但是STM32F4整体才150mA,直接驱动会非常浪费资源,因此IO口并不是直接驱动,而是通过三极管扩流后再驱动蜂鸣器。% Z" e, l# ]5 K* y

) b5 {, h( F% |+ _/ v' ~& l3 d
: M# [" `5 M# M; |
二、机械按键简介
6 H7 H( \& s; f) e& h  A开发板上搭载的是机械微动开关按键,这种按键在使用时需要注意其抖动,按下时,信号不会立刻稳定/ K3 v$ w% C7 t  Z8 ]' m2 }
: o# c8 f1 n* @- Y
需要进行按键消抖,这里通常采用软件程序消抖的方法来避免抖动。# j" }- v2 f& G: @( t7 |2 Z
2 i3 k& }' ~( e; U6 m$ O# _. f! L
7d38de8345a94553b806d94f4ad9a1be.png
5 e6 h& i2 X* n1 E, U
% q! h8 Q1 v- Z! [. P" L三、GPIO配置简介" X* y+ O) }6 C7 j$ ]

9 v8 g7 x. x* G2 c1 ^, B

5 k( D. h# T9 ]# k7 C* P8 i7 F实践学习
4 d0 [, ]% R* F. e4 o/ M一、设计规划

  \& j) p* E1 |1 f蜂鸣器实验和按键实验与跑马灯类似,都是对GPIO进行操作,因此本博文将两者放到了一起进行实现。0 J+ M8 Q  j( {- o
: \% J, Z- G7 c( M( {0 c
1.1 实验目标 ( D* E; T8 j8 z7 M( n
利用板载的4个按键,来控制板载的两个LED的亮灭和蜂鸣器的开关。
- t4 m8 }) C( N6 \" l
5 w& C# G$ D. m7 H0 {! z1 W# o
1.2 硬件资源
- I+ B% g, i3 J$ f  o% K7 B6 J3 v3 K6 |) U. C3 P+ E7 k
b00c7a51bd5d49429dc83b0efed00deb.png
  k4 v% N8 Q+ q" B9 ?9 r  e' D' O! q4 {
392de607c72d4d93bdfba2c10b2f3acf.png
: c, T5 t1 y7 \5 C9 x: c+ W0 w* W( s7 I  z! L$ f  \
6432851f0fc947ca93fe67e2df8f54f6.png . q4 f- o) A6 k( S. ~
  S) P7 F+ t5 |) V' V$ G
除KEY_UP是高电平有效(且外部无上下拉电阻,需要在32内部设置上下拉),其他按键是低电平有效。
2 U& w1 N% N8 z: q: \' L6 f7 e3 I% J8 L$ z% \- ?& P5 o- K

* J% ?% d# T5 A; k3 @+ A5 f二、程序设计
0 h' h  j1 }2 q- r% O9 _( I2.1 建立工程文件
& t# H: W. v% [9 t- L5 b
如图已经添加完的工程文件目录。
! \) P1 j/ b7 h8 w
% \' n9 q+ p+ j4 L4 s, C" K7 @
f5c85e93403f4a899aa5a5a19a8eb0df.png 0 b+ \, y/ S1 f0 [8 b! S# E; |

6 K1 T% L% `# Y8 H( X8 R$ T

: x: w' G5 \) M( r) \) t  L2.2 led配置
0 c4 x* S, b- v3 r1 B
板载对应的GPIO口为PF9/10,并将其配置为通用推挽输出模式,输出速度100MHz
7 v, A. M& Z& w
1 q2 A: _. h3 J5 Y) s
led.h文件
4 I# i2 M2 d  \! A# L  \
  1. #ifndef _LED_H
    3 h/ \2 `) }; v# L
  2. #define _LED_H
    " @$ a' ^9 q9 {) `3 }+ \6 _
  3. #include "sys.h"
    1 d: `/ O3 I3 j4 n3 g3 {
  4. //LED端口定义
    9 c8 R+ L+ p# H
  5. #define LED0 PFout(9)
    * E6 r: O1 u2 d7 p6 w. x& m0 j; v. u
  6. #define LED1 PFout(10)
      ^. J8 |8 {% G, v0 I
  7. ' A* L- D' R3 X* S3 I
  8. void LED_Init(void);; ^, y/ c8 w" n/ T$ t, h
  9. 2 z2 b: K4 o; H) }. L4 r
  10. #endif
复制代码
6 m8 R4 F/ l9 X+ S" C& H5 Y; H

9 u9 P. O$ f' I# G" |led.c文件
+ @6 m# d$ E# j* s  W( |
  1. #include"led.h"
    . |& j5 a. U8 x# v

  2. " q. c- b1 a3 ^
  3. void LED_Init(void)" \0 X0 L2 Q$ O
  4. {9 {# m5 E2 ]9 j/ n$ ]- _: h
  5.         RCC->AHB1ENR |= 1<<5;   //使能GPIOF时钟
      H: O: ~3 w1 t! m
  6.         GPIO_Set(GPIOF, PIN9|PIN10,
    : C* [* L' Y4 w) C
  7.                          GPIO_MODE_OUT, GPIO_OTYPE_PP,9 E. E5 t; t9 k6 I2 C
  8.                          GPIO_SPEED_100M, GPIO_PUPD_PU);
    " m: m. B$ z; D
  9.         //初值
      {9 I. d8 S; i4 [2 L/ e' o
  10.         LED0 = 1;
    0 H8 |( `* j- z' U( D" q9 X  F4 h
  11.         LED1 = 1;
    % a" Z$ t  V: `
  12. }
复制代码
. f2 n- _' z* Q
2.3 beep配置" [$ b' \3 ^# `3 h' S8 Y; [. y
蜂鸣器比较见到,就是一个GPIO输入 高低电平; h$ o$ G0 l9 b, h7 {8 n6 K# E
beep.h
" o' K; X  e& z, }6 K  `
  1. #ifndef _BEEP_H
    7 }4 v7 z6 s% Z  I2 q, v" K, m
  2. #define _BEEP_H
    * f" Z/ _' q4 ~; E4 U4 d' U5 j$ A0 _
  3. #include "sys.h"! s7 m, h% k  B4 I* e
  4. #define BEEP PFout(8)
    8 x! X: q- L* z3 g
  5. - ~: V' E% Z, ]! G; ?' \& ?# [
  6. void  BEEP_Init(void);
    ( \; g) `( g0 R7 U  W

  7. % O* c  Q' l8 k( ?2 H. O
  8. #endif
复制代码
* c, w, Z! h& `/ T: G( f
beep.c/ s" h% a! n4 z. y1 B( W; F, G
由于蜂鸣器是高电平有效,因此将端口配置为下拉推挽输出
+ K; @2 S0 F- I  g, o* ]" t" V
  1. #include"beep.h"8 s6 S% a: O2 [- T9 ]$ ~

  2. : R# J! r' \0 y8 h( J
  3. void BEEP_Init(void)  i" D- N: a4 d( p( l. s
  4. {& F) A' e9 S9 ]4 L/ ?! L
  5.         RCC->AHB1ENR |= 1<<5;. }9 a% m+ a: G. V, h8 t
  6.         GPIO_Set(GPIOF, PIN8,! e7 D8 S$ A5 C7 f, y
  7.                          GPIO_MODE_OUT, GPIO_OTYPE_PP, 2 L, _9 W! G- y; T7 ~" V/ w
  8.                          GPIO_SPEED_100M, GPIO_PUPD_PU);  B) c$ i4 @: D" P& f( c: E
  9.         BEEP = 0;   //初值关闭蜂鸣器5 H5 Q1 J# B" D9 H
  10. }
复制代码

3 i8 f" F/ Z3 X% |+ r- i3 N4 a2.4 key配置
: Y# K  U2 t+ f9 |key.h, p3 C( M4 a0 e! Q8 }+ F
  1. #ifndef _KEY_H- F0 G8 Z* |( R. y& j
  2. #define _KEY_H; T7 S" d  r7 l. k, ~/ j# t
  3. #include "sys.h"" V. x6 n1 V$ _$ n* @1 a& w
  4. #define KEY0  PEin(4)   //PE4
    $ y3 z" U0 ^- ~2 w+ e2 n
  5. #define KEY1  PEin(3)        //PE3- q: A$ `* ~* h+ }5 \2 B! G
  6. #define KEY2  PEin(2)        //PE2! C# o! x) W, {7 I& n  `
  7. #define WK_UP PAin(0)        //PA0, b' j( Q4 i' ^
  8. #define KEY0_PRES 1   //KEY0
    $ [" \: z6 ^: _: K0 Q# P/ Y
  9. #define KEY1_PRES 2   //KEY1
    - `' U! {) n4 `3 ^1 V
  10. #define KEY2_PRES 3   //KEY2 * A3 x# V$ y+ y1 g6 }
  11. #define WKUP_PRES 4   //KEY_UP ( WK_UP)
    . }& z. j/ r" v+ W" t3 ~

  12. & k; g: v8 Q" W5 Q9 |8 B
  13. void KEY_Init(void);# \: V+ w* w; a, F
  14. u8 KEY_Scan(u8 mode);       //按键扫描函数
    2 I$ Z9 [  b4 K" a  e/ q0 t
  15. 9 k8 k' q& F" t+ y2 s) n! g! {. T& |
  16. #endif
复制代码
1 `3 c% y' D$ O+ e+ K; I* G
key.c
2 |9 k4 u5 J8 Y6 @
  1. #include"key.h"3 m: W& l" B$ z! u' \- g( T7 Z9 j4 k
  2. #include"delay.h"     //ÐèÒªÑÓ³ÙÅжÏÏû³ý¶¶¶¯* ]" ~6 k3 \! }7 ^, t/ {4 p
  3. void KEY_Init(void)
    " S: c" L; S) M
  4. {+ z4 d* p8 n8 d3 v( S8 Y, v4 |  H
  5.         RCC->AHB1ENR |= 1<<0;    //GPIOA( o) ?6 u  Z+ s5 Z3 K1 _& |
  6.         RCC->AHB1ENR |= 1<<4;    //GPIOE# n/ N: Z: G( x
  7.         GPIO_Set(GPIOA, PIN0, GPIO_MODE_IN,4 q- D  \0 l9 S8 x7 @
  8.                          0, 0,                         
    $ X: G& S$ e1 [" R" p% x% u6 ~* {
  9.                          GPIO_PUPD_PD);     //PA0 高电平有效因此为下拉2 y5 N, d- m% \9 v
  10.         GPIO_Set(GPIOE, PIN2|PIN3|PIN4, GPIO_MODE_IN,. o( x& F! g/ n# Q& J6 r. C" A
  11.                          0, 0,# c4 e# S" F0 @/ {5 C* u9 v
  12.                          GPIO_PUPD_PU);     //低电平有效,上拉
    1 c' T- Y- k! F7 s
  13. }
    / Y$ T- O3 G6 G
  14. u8 KEY_Scan(u8 mode)
    ) s3 I; }$ Q1 w- l' t2 A
  15. {, b' t$ H/ f1 W2 c3 s* k
  16.         static u8 key_up = 1;   //静态局部变量
    ' @: S( n3 I; b9 i1 D6 o# ~
  17.         if(mode) key_up = 1;    //当有按键按下时,按下标志
    4 D" o7 y/ P% ?+ v
  18.         if(key_up && (KEY0==0 || KEY1==0 || KEY2==0 || WK_UP==1))  
    8 U! `% N- n/ _& a8 c. X* D* A
  19.         {! t' j+ V# S/ W
  20.                 delay_ms(10);       //ÑÓ³ÙÅжϣ¬ÒÔÏû³ý¶¶¶¯4 T) l' I# ]( J* |' P) L- K
  21.                 key_up = 0;
    4 F5 F1 X& v8 ?/ ^( m2 }& q+ p
  22.                 if(KEY0==0) return 1;* e$ ]& s& d; I0 e; A: q3 S
  23.                 else if(KEY0==0) return 1;
    ) K# H- E1 S' b! ^6 \* Z
  24.                 else if(KEY1==0) return 2;
    ) l1 f& B7 a) V& ]
  25.                 else if(KEY2==0) return 3;5 j# x# R! m8 z5 d4 I' y- }
  26.                 else if(WK_UP==1) return 4;
    2 T: i2 J0 b9 A% d6 I5 h+ z
  27.         }
    2 J! K5 F& q" \3 u( @1 R7 I
  28.         else if(KEY0==1 && KEY1==1 && KEY2==1 && WK_UP==0)
    9 n7 @  m8 S; {& A; Y. R
  29.                 key_up =1;% p7 b) n) n! I
  30.         return 0;    //ÎÞ°´¼ü°´ÏÂ8 ~1 I, O; d2 k# q+ F9 D, h
  31. }
复制代码

* F! b3 P, j. d一定要注意高低电平有效,本人在敲代码的时候PA0(高电平有效)设置为了上拉(有问题);PE2-4(低电平)设置为了下拉(错误)。   如果这样设置就会出现,按键是否按下一直有效,因为按下也是相应的状态。 , C. Y/ H1 n5 S/ l1 Y

% k- R: c7 j! O' H
3 ]! X& N7 x( x4 S
2.5 主函数text.c
* E7 O$ u5 V- A
  1. #include "sys.h"; L) \4 c( @; t$ O: Z: t1 O9 i
  2. #include "delay.h"
    ( i4 F2 f9 b8 r8 B! p* o
  3. #include "led.h"' R, G* _5 r& i
  4. #include "beep.h"
    & u4 c" h2 b: D, x$ }: K, n
  5. #include "key.h"
    ; ~( B5 R' V4 O! H; F3 m  |
  6. int main(void)8 E4 k* r5 ]0 |( [
  7. {3 D* `. o6 q' x! F2 g: w" L8 v/ ~% B
  8.         u8 key;' H% L5 I* u6 ?- Y6 Q2 P$ p
  9.         Stm32_Clock_Init(336,8,2,7);   //设置时钟 168M3 R3 j) ~% I0 f0 p; y- O: Q* P, ^
  10.         delay_init(168);0 {' g  e: i3 Y9 K. N. ~9 l& {
  11.         LED_Init();
    / s4 c' q+ M. n2 G( _$ p5 o0 |- q
  12.         BEEP_Init();
    : G+ U  A" Z. A" z
  13.         KEY_Init();
    % w$ U& j5 P+ M, b# W% _4 ]
  14.         LED0 = 0;
    ! L* p! _% ^9 e/ E6 m
  15.         while(1)
    * N- o6 p+ ?/ z0 C, k' |4 `' A
  16.         {
    + H( j9 Y; ~& s
  17.                 key = KEY_Scan(0);   1 \  P' R8 O0 E3 J
  18.                 if(key)
    ' `# U. u8 c3 _9 k5 w" K. t
  19.                 {
    7 s. h) y# o  T9 w% S: Y, L
  20.                         switch(key)
    ) a" Y% W! {# T; L
  21.                         {
    ' N5 P( o# M. d" R& z7 E0 ~
  22.                                 case WKUP_PRES:   
    - m' q5 [; z3 u: Y1 G0 N
  23.                                         BEEP =! BEEP;
    9 A; U- `' x7 y! w9 H
  24.                                         break;+ g) U" [+ A6 x) d& k9 i# B9 E
  25.                                 case KEY2_PRES:: Y3 H2 M+ p# f: ~" V) {1 r& B
  26.                                         LED0 =! LED0;" {: \. V5 x1 J) h
  27.                                         break;" B) D, C6 v0 i! Q8 \5 Z8 B
  28.                                 case KEY1_PRES:0 t- o! k1 S' y1 [( [( ?
  29.                                         LED1 =! LED1;/ J- s7 p! c+ n, g; |/ ?
  30.                                         break;                               
    ' Z/ b% S) A2 @- b- H: J
  31.                                 case KEY0_PRES:' X7 J1 o. k3 w5 c0 ^
  32.                                         LED0 =! LED0;
    ; m: r  @; ]$ _* a
  33.                                         LED1 =! LED1;4 S- U8 a3 i& I, {
  34.                                         break;                                                                                                        + m3 r( W! Y3 @- E$ g; I/ P
  35.                         }  
    ) v1 G, L3 _( u
  36.                 }else delay_ms(10);                             
    ; E2 Y+ I( S7 _0 V6 M
  37.         }       
    4 W! I+ B$ H# R' j7 Q# F
  38. }
复制代码
- z# [' v7 E  H7 P
' f+ q7 u# I  }: L6 ~3 M* s
三、在线调试
" a# x4 Q0 _9 E4 J. L' C/ Q8 C/ x1 R下载完成完成后,打开调试,点击运行,并调出相关的寄存器。/ p1 R1 h, e$ T: J9 P

  r  P; L0 Y; |4 h, O( E1 ^3 W3.1 相应寄存变化' D6 M6 P$ Z2 E8 N) p9 z" P
按键GPIOE口,可以看出按键的相关位的状态,如图由于按键低电平有效(上拉),此时相应的位被拉高。
. F& o: c6 a7 r  d5 H
8 ]3 e+ R0 A0 l% O( q* S
8369b7bda7cc4532818e39747cad0995.png 3 }8 [0 E+ u/ N0 a' J

  I/ x& h  j4 R5 @2 B" `
9 w  q4 x3 G. W# r
LED灯/蜂鸣器的GPIOF口,输出数据ODR 寄存器状态(低电平有效),默认LED0亮;蜂鸣器高电平有效(不响) 。
8 `/ x# Q6 U( I( b/ E) F: J2 [6 m. c2 u8 O5 x
1dde5bf01ed24739bbb312050e7bf766.png
3 l* ~- F( N$ S6 \9 ?
! C, S- q; W% V 当KEY0按键按下时,PE4由高电平变为低电平,LED0,LED1状态转换0 P, ?+ M) {3 ?! e2 i* m2 e

' d1 {4 {/ y0 r
a43af789c34b454a8985e5a4f9f31c2a.png : {2 Q0 ?! t. M# H2 m& g/ w% q
1 `# {! C1 m/ r
bb8dd2de10c4420f8dc1e7d1df31f7cd.png
( p- a4 \- }( s  B: G4 Z
  K- C9 x  N  F, U1 w9 e 蜂鸣器类似,这里不做演示。8 t/ u) ~- g9 Q
5 r" m6 Y6 m$ t" Q6 Y1 y5 _+ a

) `+ b, V; h3 @+ v3.2 关键变量变化
$ j- a- F4 Y: z. W' [点击可以添加变量,然后添加变量;也可以直接选中变量点击右键选择“add "key"to Watch1。
2 X% ?. m4 G# e5 b+ l3 W- J" H: d! f( ^2 V
8dca08f5f7c44f659217a404eca5f43f.png
  Z- ?9 Z4 D+ V# ?9 O; b# R) [
5 w9 ?9 k9 U; k: ^在变量key后面打一个断点,将代码运行到此) f9 `* ], T, L( ]* ]; A
" D! ]/ T; H; w7 H$ J/ C+ E
ca43e4496bda4355a4b577fee564ebb1.png 1 h4 g! i8 F  ]0 ]
" X0 `: T3 A2 x3 N/ ]2 {
在板子上按下KEY0,可以观察到扫描函数返回值,key=1。与上面的寄存器变化相对应。: L# ~$ R: u0 X' ]; X

* {1 B  D, p# w) n, C7 a8 M
4041625bc53b433d8db0936b1229c7cc.png
" \& w* {% Z  A3 H* \; c! e3 C. U. `9 H1 P8 u
四、上板验证6 Z1 l9 ^) t# L! Y8 @2 ^! u" _1 y- G
整体编译没有问题:
) }; _) @# I8 J  H8 z
: c3 S" V; o6 v( y! H
f39b3e7082914a40a6ed2de71c5866ea.png - r, C1 S) C! ~; T/ W

: M! P. M7 Z9 ]+ N( s- B 下载到板卡中即可实现相应的功能。
% F0 J. D. o+ A, |: H2 q————————————————
( j0 e0 s. S, H9 n9 E# u1 u# l4 h( i! j版权声明:追逐者-桥
* z8 c& x9 ^/ |* K2 O% }+ C$ {$ a如有侵权请联系删除9 u& ~) O/ ~& q# x) ^

5 N8 @( J& P8 v* l' [8 V# H/ D" {0 J

) ~' |- Z7 b/ W- c. V& s0 y
收藏 1 评论0 发布时间:2023-3-10 10:39

举报

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