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

【经验分享】STM32实例-蜂鸣器实验

[复制链接]
STMCU小助手 发布时间:2022-7-1 12:25
通过 STM32F1 芯片的一个 IO口控制板载有源/无源蜂鸣器,实现蜂鸣器控制。
/ B) Q; |* C! \1 }
蜂鸣器介绍
    蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
    压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号,阻抗匹配器推动压电蜂鸣片发声。
    电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
    其实一句话就可概括它们之间的区别,想要压电式蜂鸣器发声,需提供一定频率的脉冲信号;想要电磁式蜂鸣器发声,只需提供电源即可。无源蜂鸣器,属于压电式蜂鸣器类型;有源蜂鸣器,属于电磁式蜂鸣器类型。这里说的有源,并不是指电源的意思,而是指蜂鸣器内部是否含有振荡电路,有源蜂鸣器内部自带振荡电路,只需提供电源即可发声,而无源蜂鸣器则需提供一定频率的脉冲信号才能发声,频率大小通常在 1.5-5KHz 之间。有源蜂鸣器实物如下图。
) n" K0 V( }( \0 y! ~
微信图片_20220701122353.jpg
, j' ?6 r" _9 P0 V$ h
    如果给有源蜂鸣器加一个 1.5-5KHz 的脉冲信号,同样也会发声,而且改变这个频率,就可以调节蜂鸣器音调,产生各种不同音色、音调的声音。如果改变输出电平的高低电平占空比,则可以改变蜂鸣器的声音大小。

6 z/ p% q  b7 G. y* b0 I
硬件设计
    在前面我们已经对 STM32 的 GPIO 做了简单介绍,并且还使用了其中
IO 口直接控制开发板上的 LED。对于本章要实现蜂鸣器的控制,我们能否直接使用 STM32 的 IO 口驱动呢?根据 STM32F103 芯片数据手册可知, 单个 IO 口的最大输出电流是 25mA,而蜂鸣器的驱动电流是 30mA 左右,两者非常接近,有的朋友就想直接用 IO 口来驱动,但是有没有考虑到整个芯片的输出电流,整个芯片的输出电流最大也就 150mA,如果在驱动蜂鸣器上就耗掉了 30mA,那么 STM32 其他的 IO 口及外设电流就非常拮据了。所以我们不会直接使用 IO 口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样 STM32 的 IO 口只需要提供不到1mA 的电流就可控制蜂鸣器。所以我们也经常说到 STM32 芯片是用来做控制的,而不是驱动。开发板上的无源蜂鸣器模块电路原理图如下所示。
微信图片_20220701122712.jpg
; |/ ^/ R& R# k) U
微信图片_20220701122715.jpg

/ O: R3 ^2 N2 G! R) u* T
    开发板上的有源蜂鸣器模块电路原理图如下所示。

3 l1 \* v2 Z: W* V* i0 D4 q
微信图片_20220701122719.jpg
: h3 h( Q' o+ [
    从这两个电路图可以看到, 无源蜂鸣器的控制需要给其一定频率的脉冲才能发声,仅给一个高电平或者低电平是不能发声的,因此蜂鸣器模块电路直接将STM32引脚接在NPN三极管的基极上, 然后三极管的发射极连接蜂鸣器,无需考虑外界对 PB5 脚产生的高低电平会对蜂鸣器发声干扰。如果使用的是有源蜂鸣器,它只要有电源就会发声,因此就必须考虑外界对 PB5 引脚电平的干扰问题。通过电阻 R06 和 PNP 三极管 TP6 进行电流放大,从而驱动蜂鸣器。电阻 R66 是一个上拉电阻, 用来防止蜂鸣器误发声。 当 PB5 引脚输出低电平时, PNP三极管导通,蜂鸣器发声;当 PB5 引脚输出高电平时,PNP 三极管截止,蜂鸣器停止发声。

# D  h/ M: b$ {" Y3 I
软件设计
蜂鸣器初始化函数
    打开工程中 beep.c 文件,里面代码如下:
  1. #include "beep.h"; G6 s: X' I  m$ O& p
  2. $ k& P) ^6 @' ?) G$ \9 t
  3. /***************************************************************** p! L4 `6 _( Y, l' h& [
  4. & h% Q( e  ?/ n1 L! D2 `4 x
  5. ***************9 n$ c4 n) K7 h
  6. " ?5 G3 s; C4 p4 [$ {1 q
  7. * 函 数 名 : BEEP_Init
    ! ?+ f/ [2 ?2 N1 v3 b

  8. 2 y7 o! l) \6 H6 p
  9. * 函数功能 : 蜂鸣器初始化
    & `& h9 ^  H3 O2 K: b
  10. ; J3 o5 t8 s' Y7 j
  11. * 输 入 : 无3 E) m! m+ e* z1 ^! j3 I

  12. 3 u3 b, ?1 j3 O0 D+ ~; X
  13. * 输 出 : 无
    - h7 ?- ~. p% s% m( ~
  14. ( r+ i- E! H& b& j
  15. ****************************************************************/
    4 Y  `& h0 O' O- I& t8 H

  16. 0 `) l) w. R6 M6 K7 H
  17. void BEEP_Init() //端口初始化
    " k# L: Y. \$ m. T6 c: e, b

  18. 5 x8 \% M6 Y1 V; W! o4 i4 w
  19. {
    4 V% C5 s. t! {; T( i- ~) K
  20. ) {- q: E$ Z+ }( a
  21. GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO# g# A8 m1 D3 r

  22. - M+ M5 B3 d# k( b
  23. RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE); /* 开启 GPIO 时钟 */6 G/ l3 t3 @6 d8 @4 K- T6 x, m
  24. 6 y! u4 V. g6 i% H7 [
  25. /* 配置 GPIO 的模式和 IO 口 */
    7 u, N: t: X- C  |& w) F
  26. $ z1 r  x9 I7 k' W( H& n4 @+ X$ i. C
  27. GPIO_InitStructure.GPIO_Pin=BEEP_PIN; //选择你要设置的 IO口
    # U, W8 R8 P- h6 Q
  28. , b. w* h: j: ]) T/ I& I  v
  29. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
    " r' ?% [. G6 J5 f
  30. + ^3 [# Q" H( `: w* G3 O" v2 e: r
  31. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
      H6 h6 c6 X5 y3 y9 ]" [% [

  32. 6 R7 \  D; U5 Q, k
  33. GPIO_Init(BEEP_PORT,&GPIO_InitStructure); /* 初始化 GPIO*/0 d0 [1 L9 i' K7 R2 }

  34. & x( b& {' b/ n/ l! p0 B$ t! |
  35. }
复制代码
  @: ]. d& {- W2 S
    BEEP_Init()函数用来初始化蜂鸣器的端口及时钟,在函数内我们看到有几个参数不是库函数内的,比如 BEEP_PIN、BEEP_PORT、BEEP_PORT_RCC,这种情况一般是我们自己定义的宏,通常放在对应的头文件内,我们打开 beep.h,可以看到如下代码:
  1. #ifndef _beep_H1 C' ^, W8 z) ?" ]  Y

  2. # _5 t& R0 P& |- ^; M4 C5 x  W: Z
  3. #define _beep_H
    ; r0 Z' T$ \( O+ y8 l

  4. 8 t9 J& t. |9 q/ Z
  5. #include "system.h"
    . H; Y$ O: F. s4 [2 ?/ V# q

  6. 1 W! e; ?* G" ~0 ?) [' {5 Y
  7. /* 蜂鸣器时钟端口、引脚定义 */
    2 i  k; b; b* b& O# S

  8. 7 x9 C2 H: C8 i* I& X
  9. #define BEEP_PORT GPIOB
    ( L6 A" T( z: s  i8 ^
  10. 0 k2 i3 r1 b2 Q# ?1 R9 b
  11. #define BEEP_PIN GPIO_Pin_5
    8 i& @* S0 w1 f# d! S
  12. 0 E- T8 s: ]3 j
  13. #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB) D3 A# ]6 K; L' x, P

  14. $ ?1 {8 D$ n' |3 ^9 w# [, j
  15. #define beep PBout(5)
    5 ^5 X3 K( Q( u5 X6 q6 {. T7 ]" }
  16. ) Y0 J5 \% k+ }+ ^2 P# k
  17. void BEEP_Init(void);
    0 U* S4 r1 H5 X) G: `
  18. ' {/ @4 ^2 o. p4 R+ K2 [% [
  19. #endif
复制代码
4 g5 x, ~, X7 b
    里面就将蜂鸣器的GPIO 端口及管脚进行了宏定义,这样做是方便大家移植程序,只需要对这个宏修改就能实现蜂鸣器的初始化修改。
( s3 ~% P& ]3 {& m- I* M
主函数
    我们打开工程中 main.c 文件,里面代码如下:
  1. /****************************************************************
    ! C% T, C6 o4 D  E
  2. - D" A0 V+ x/ C& }2 [( D  u; ]
  3. * 函 数 名 : main, J! G+ y4 x) I0 \& J- j* C

  4. / z: ?; X3 e- @% f. _$ Q9 K
  5. * 函数功能 : 主函数/ ]' O& H" Q% X) X$ s. w

  6. 3 l% V; {( \3 C9 Z
  7. * 输 入 : 无; P  u9 A. L2 I6 i, D6 n  \

  8. 9 a, k7 [9 M# @( y
  9. * 输 出 : 无8 B: Z& `" I+ P0 s

  10. ; G! Z8 s: s  j" P& g, z/ X
  11. ****************************************************************/8 d: m$ k! b0 t& j# h6 u# ]' a

  12. 8 ^7 Y* C- a4 a8 W" y- e
  13. int main()# K# H, V4 a! Q

  14. , I$ R; \$ K4 [$ C
  15. {3 f$ J2 m# i; ]: o0 G- P+ i

  16. 6 q6 N& W; P$ `
  17.     u16 i=0;
    ! c; R- r' k: X8 q7 E9 L7 {
  18. ( A" i% p$ D% t+ ~/ i
  19.     SysTick_Init(72);
    ! R# W- V! @$ w  O2 ]9 _& ]0 N

  20. & |" k% z* z6 ^& a. j
  21.     LED_Init();
    ; k+ p' B( o( D3 C; s: u
  22. . |5 ?8 l8 E  u  E$ p
  23.     BEEP_Init();/ A+ @7 g& O- @, T3 l( D# j" f
  24. 9 e& W  `4 r% y0 A1 [
  25.     while(1)
    , T( x+ O8 m8 w1 K* ]' P9 [
  26. * j: b6 N  d- C8 j( H
  27.     {" }( @& |* r  }" j+ G+ G0 L- \
  28. # D  ]0 K2 s. c& Y1 Z4 E& y
  29.         i++;
    1 h* _0 ]. Z' o- O7 ]% {1 C, ]
  30. 1 t4 I/ z* z" h1 x  t& W
  31.         if(i%10==0)
    ) ]1 C1 [: Y% V; @2 G. y/ K

  32. + T9 m5 h5 g- h5 Z1 \
  33.         {' Z" {& R6 {+ m* q  @4 p% j
  34. + e' n6 n; j2 `% B
  35.             beep=!beep;( r; X& m& f0 D% \1 a8 K& Z

  36. ' N1 b( W' N$ k
  37.         }
    + }* q( _& M7 E- j( H
  38. 6 u, _" T8 f  Z1 ?
  39.         if(i%20000==0)
    , {2 l: ?& A# P3 U( e5 G6 Q
  40. 9 y- m: N- q7 X' `; G
  41.         {; O0 F& m8 D# g! h) \' X

  42. # C2 v/ M, t$ f7 q4 y. v. S5 w
  43.             led1=!led1;
      Q3 p, {$ U9 ~* ^/ @, e( m
  44. 0 M% U3 Z0 \! ^5 ?
  45.         }
    " [" ?. }+ F& V
  46. ( E' o1 p8 M- [# n3 u
  47.         delay_us(10);
    5 X0 s/ s3 z5 v

  48. , }3 H* b6 B# A! r# z& y2 @- ^
  49.     }
    % J- h( J3 J  ~2 t3 _

  50. : L% j5 b/ k, L; x5 P  Y
  51. }
复制代码
( s7 Y+ O2 N' w  b$ N5 i. q
    主函数实现的功能比较简单,首先将使用到的外设硬件进行初始化,然后进入 while 循环,间隔 100us 对蜂鸣器管脚电平翻转,这样就产生了一个频率为5KHz 的脉冲,因此无源蜂鸣器就会发声,当然有源蜂鸣器的控制可以更简单,只需要给它一个低电平即可,为了实现 2 块板子程序的兼容,这里就统一采用此种方式控制蜂鸣器。间隔 200ms 对 led1 管脚电平翻转,因为使用到了 delay_us延时函数,所以在 main 函数开始处就需要调用 SysTick_Init(72)初始化,这个在我们后面所有程序都会使用,后面就不重复。
    将工程程序编译下载到开发板内,可以看到 D1 指示灯间隔 200ms 闪烁,蜂鸣器发声。
. ~9 U4 [% _! q- M& G2 l7 ]
赞 收藏 评论0 发布时间:2022-7-1 12:25

举报

0个回答

所属标签

相似技术帖

官网相关资源

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