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

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

[复制链接]
STMCU小助手 发布时间:2022-7-1 12:25
通过 STM32F1 芯片的一个 IO口控制板载有源/无源蜂鸣器,实现蜂鸣器控制。

( A  G7 A$ g% p( H$ e. z
蜂鸣器介绍
    蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
    压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号,阻抗匹配器推动压电蜂鸣片发声。
    电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
    其实一句话就可概括它们之间的区别,想要压电式蜂鸣器发声,需提供一定频率的脉冲信号;想要电磁式蜂鸣器发声,只需提供电源即可。无源蜂鸣器,属于压电式蜂鸣器类型;有源蜂鸣器,属于电磁式蜂鸣器类型。这里说的有源,并不是指电源的意思,而是指蜂鸣器内部是否含有振荡电路,有源蜂鸣器内部自带振荡电路,只需提供电源即可发声,而无源蜂鸣器则需提供一定频率的脉冲信号才能发声,频率大小通常在 1.5-5KHz 之间。有源蜂鸣器实物如下图。

! f3 q' R. r4 T: f* k
微信图片_20220701122353.jpg
# r) u* D( M4 {
    如果给有源蜂鸣器加一个 1.5-5KHz 的脉冲信号,同样也会发声,而且改变这个频率,就可以调节蜂鸣器音调,产生各种不同音色、音调的声音。如果改变输出电平的高低电平占空比,则可以改变蜂鸣器的声音大小。

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

" c9 j* t% ?# L+ \& r! ~
微信图片_20220701122715.jpg
& u+ E0 @' g& C: I5 L# Q: ^0 p# A. R
    开发板上的有源蜂鸣器模块电路原理图如下所示。
; _, q0 s9 X. k# L% E" y, z3 i
微信图片_20220701122719.jpg
& K4 H( m5 k5 I; E+ A9 A' M
    从这两个电路图可以看到, 无源蜂鸣器的控制需要给其一定频率的脉冲才能发声,仅给一个高电平或者低电平是不能发声的,因此蜂鸣器模块电路直接将STM32引脚接在NPN三极管的基极上, 然后三极管的发射极连接蜂鸣器,无需考虑外界对 PB5 脚产生的高低电平会对蜂鸣器发声干扰。如果使用的是有源蜂鸣器,它只要有电源就会发声,因此就必须考虑外界对 PB5 引脚电平的干扰问题。通过电阻 R06 和 PNP 三极管 TP6 进行电流放大,从而驱动蜂鸣器。电阻 R66 是一个上拉电阻, 用来防止蜂鸣器误发声。 当 PB5 引脚输出低电平时, PNP三极管导通,蜂鸣器发声;当 PB5 引脚输出高电平时,PNP 三极管截止,蜂鸣器停止发声。
8 m  ]! K* H2 `3 i+ S1 E
软件设计
蜂鸣器初始化函数
    打开工程中 beep.c 文件,里面代码如下:
  1. #include "beep.h"
    $ \2 _' `) d) s* V; [! h$ D
  2. ! S- m$ l3 l2 e- k6 |7 u& \1 k
  3. /****************************************************************' @. B# W/ g# S) W5 _4 B3 _! Z

  4. - b" W9 J# `9 M: V) J
  5. ***************1 b( }9 O# r- ~

  6. 9 h& a) f/ e4 @" |0 O( O
  7. * 函 数 名 : BEEP_Init
    6 W- V% d) X  V  x7 e
  8. 3 k% p- s; G2 ~9 V" q  i+ e" Q5 h
  9. * 函数功能 : 蜂鸣器初始化: L% d& v) t- U3 [8 D/ t# n

  10. ) T* r* B/ U  C4 e% d0 w7 [
  11. * 输 入 : 无
    9 b1 T; e% K6 k$ q4 h. e5 }% t

  12. 4 ^0 q4 @  A4 E4 j* z: F7 A3 c
  13. * 输 出 : 无
    * d" u, B( n1 m

  14. / ^& B( S, u4 G
  15. ****************************************************************/
    . A2 u: ?- `( j) ~9 g- ^- `
  16. & |, {0 T! G5 M+ |. G
  17. void BEEP_Init() //端口初始化& Z' V" R! v: W5 ?5 D
  18. & Z2 j( ~7 v! ^! `% M% S
  19. {7 m8 T/ O) ^; b) ~

  20.   i+ f& _$ N* X2 t& {* l5 J
  21. GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO
    3 q/ x3 V5 T9 J( [& x/ y
  22. 8 h8 u/ C% ]2 E7 j. X
  23. RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE); /* 开启 GPIO 时钟 */) ], L2 o! d$ a: K1 P( N# B3 l
  24. : S% V5 u1 q& t7 `6 K1 A- K
  25. /* 配置 GPIO 的模式和 IO 口 */
    * e1 ?* }7 F. _" ^% h  ]1 j
  26. ; r' S& u$ z- }: G' j, b3 M# P
  27. GPIO_InitStructure.GPIO_Pin=BEEP_PIN; //选择你要设置的 IO口+ ~( E8 h- R; N- d) i, |3 B+ E" r

  28. . G  L/ f; B' v  S" p# ?4 l
  29. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
    7 V5 M' r0 Q' Q* T

  30. ; k% L3 D0 X2 P; M$ c
  31. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率$ {' ~; L+ l$ o  r" I& M
  32. % E, |# ?7 N. @6 \
  33. GPIO_Init(BEEP_PORT,&GPIO_InitStructure); /* 初始化 GPIO*/( O) }/ S. g+ l) Z/ j; b5 P' M
  34. 7 M3 c5 q4 l8 C7 E7 w
  35. }
复制代码

+ C- Z3 `0 `. C
    BEEP_Init()函数用来初始化蜂鸣器的端口及时钟,在函数内我们看到有几个参数不是库函数内的,比如 BEEP_PIN、BEEP_PORT、BEEP_PORT_RCC,这种情况一般是我们自己定义的宏,通常放在对应的头文件内,我们打开 beep.h,可以看到如下代码:
  1. #ifndef _beep_H
      |7 n0 j7 v* _/ o6 U* S$ ?8 D. G

  2.   o9 {+ p. l- x* C
  3. #define _beep_H8 d1 z3 S( ?+ C1 \8 |& t/ k

  4.   J* m% `2 L/ A. N% ~, p7 o) @
  5. #include "system.h"
    ! }2 C, J8 a% T

  6. : @. U1 b7 n3 z9 e. t% B* {* U
  7. /* 蜂鸣器时钟端口、引脚定义 */
    + z2 j8 u1 K2 j) ^

  8. 8 `% `# ]6 E! A3 K. ?/ R! Q
  9. #define BEEP_PORT GPIOB3 }5 b, ~" E; W( i, }# |

  10. 3 _* l0 j7 O7 R0 y
  11. #define BEEP_PIN GPIO_Pin_5
    : s6 S" z5 a  J. e5 Z1 V! _% x
  12. 4 r* z# k# M% G  s6 e
  13. #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB
      p& ~& F- r" j8 n* A( w% z$ d
  14. + O! e0 F7 B" e+ W
  15. #define beep PBout(5)% k2 _/ w+ K* |) u2 `

  16. 6 u8 K; i# i& b+ J
  17. void BEEP_Init(void);
    ( H; P. Y; p, x8 O# n9 `

  18. ( j( [6 v* A1 v8 v: U7 y6 K  A6 g
  19. #endif
复制代码
. t& R8 N* O4 w2 x+ Y
    里面就将蜂鸣器的GPIO 端口及管脚进行了宏定义,这样做是方便大家移植程序,只需要对这个宏修改就能实现蜂鸣器的初始化修改。
7 B# W9 W" @( v+ k* w: L
主函数
    我们打开工程中 main.c 文件,里面代码如下:
  1. /****************************************************************
    ' z/ j: i  R# M
  2. . s8 C* [/ g  Q" T; ^
  3. * 函 数 名 : main
    7 C' L! n) X0 V' D; i
  4. + u) A$ z3 X; r
  5. * 函数功能 : 主函数7 h: J( }: z  v  ~7 J+ o/ O

  6. - F4 x7 q9 k; b. C3 W  M
  7. * 输 入 : 无! Q, s2 H8 X# G* e! W0 d- X* C
  8. ; S" _1 p, Z, c+ ~0 B' r8 _
  9. * 输 出 : 无
    ! ^2 A2 t1 {3 Q5 D+ C, T

  10. # y# n& P; @3 N( F. _1 a+ q: ]
  11. ****************************************************************/
    * s/ H0 \8 l: e
  12. 1 h+ `" K/ s8 J1 ^; a$ p
  13. int main()( ^* a! W3 l" _8 \

  14. 2 n& Y7 l7 ?- [4 m1 J
  15. {
    & |; A9 G4 b0 ~8 n

  16. # X/ a" o( c& M! j0 J1 d
  17.     u16 i=0;) z9 ?8 \( `8 G2 s7 L

  18.   I7 k: P7 @+ D( s) l$ X5 [; V4 ^
  19.     SysTick_Init(72);% j5 }$ h( G% r
  20. 7 o3 {/ z% X0 T+ ^0 J) Y- ]
  21.     LED_Init();
    % [% {- r6 m, M, d- k9 {6 j
  22. 4 V( Y  [5 s8 Y, u; k
  23.     BEEP_Init();
    3 _$ C8 u6 q, ^
  24. / k0 N) I# j( y7 C0 N: W
  25.     while(1)
    3 T1 a; j, c1 m1 W

  26. 1 p( |! u5 h  T/ i! Q' D* Q2 G' Y
  27.     {2 K6 A' `7 M. \$ {3 S& Z* i

  28. . _, O& ~( S) T; [7 _$ Q8 V9 ]
  29.         i++;& f: B$ z3 i9 v  s

  30. ; q( b. ^4 j+ x( a; P5 I
  31.         if(i%10==0)! X# h' n1 B0 H' q
  32. % I4 d6 f) P9 J, F
  33.         {+ v; A1 d8 Y5 J7 ^7 l+ `3 L( _" f

  34. # D. S. v: K, E+ t
  35.             beep=!beep;: `. l  P8 p* f' ]$ I
  36. , ^: f  @" h8 L& }. g
  37.         }1 N. [. E# }4 T; n

  38. 3 d1 Q, R8 g' n, b
  39.         if(i%20000==0)
    5 M2 B! p6 \! h* {: `- V+ y$ _

  40. . {# L) b( l9 [2 k1 d2 ]+ J
  41.         {+ ~9 i  U! J; h) z$ ~1 y

  42. ' y5 Q& _; u$ _4 e& B7 ?
  43.             led1=!led1;
    & _! y3 t1 J% {' @6 V- A: {( }

  44. 0 s, y6 S/ D: r! M
  45.         }9 Q% ?( _# U: Q9 s. i* E  ^# D
  46. 6 \5 J: q: L6 j
  47.         delay_us(10);
    4 \9 |  x7 s( `7 J! x: @

  48. 7 }# T" `2 _. O! o
  49.     }
    , n& L4 a7 r3 `& G

  50. " l! T, a$ K$ m- s
  51. }
复制代码

; J% d* N1 z& G8 _
    主函数实现的功能比较简单,首先将使用到的外设硬件进行初始化,然后进入 while 循环,间隔 100us 对蜂鸣器管脚电平翻转,这样就产生了一个频率为5KHz 的脉冲,因此无源蜂鸣器就会发声,当然有源蜂鸣器的控制可以更简单,只需要给它一个低电平即可,为了实现 2 块板子程序的兼容,这里就统一采用此种方式控制蜂鸣器。间隔 200ms 对 led1 管脚电平翻转,因为使用到了 delay_us延时函数,所以在 main 函数开始处就需要调用 SysTick_Init(72)初始化,这个在我们后面所有程序都会使用,后面就不重复。
    将工程程序编译下载到开发板内,可以看到 D1 指示灯间隔 200ms 闪烁,蜂鸣器发声。

+ y- o9 A1 a7 M* D0 D( P/ z
收藏 评论0 发布时间:2022-7-1 12:25

举报

0个回答

所属标签

相似技术帖

官网相关资源

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