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

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

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

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

: o* L* w& Q9 ]
微信图片_20220701122353.jpg

% u$ z: W/ l% g- a4 ?" h
    如果给有源蜂鸣器加一个 1.5-5KHz 的脉冲信号,同样也会发声,而且改变这个频率,就可以调节蜂鸣器音调,产生各种不同音色、音调的声音。如果改变输出电平的高低电平占空比,则可以改变蜂鸣器的声音大小。
& K) h* f( Z4 P6 g0 Y
硬件设计
    在前面我们已经对 STM32 的 GPIO 做了简单介绍,并且还使用了其中
IO 口直接控制开发板上的 LED。对于本章要实现蜂鸣器的控制,我们能否直接使用 STM32 的 IO 口驱动呢?根据 STM32F103 芯片数据手册可知, 单个 IO 口的最大输出电流是 25mA,而蜂鸣器的驱动电流是 30mA 左右,两者非常接近,有的朋友就想直接用 IO 口来驱动,但是有没有考虑到整个芯片的输出电流,整个芯片的输出电流最大也就 150mA,如果在驱动蜂鸣器上就耗掉了 30mA,那么 STM32 其他的 IO 口及外设电流就非常拮据了。所以我们不会直接使用 IO 口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样 STM32 的 IO 口只需要提供不到1mA 的电流就可控制蜂鸣器。所以我们也经常说到 STM32 芯片是用来做控制的,而不是驱动。开发板上的无源蜂鸣器模块电路原理图如下所示。
微信图片_20220701122712.jpg
# h, K% `6 n! U3 c) `& E: r  D
微信图片_20220701122715.jpg

6 C" o% {! Y) p
    开发板上的有源蜂鸣器模块电路原理图如下所示。
+ L5 ?# n  Q) L# d1 t# v  G$ \
微信图片_20220701122719.jpg
! O8 H1 O3 f( B  U  T
    从这两个电路图可以看到, 无源蜂鸣器的控制需要给其一定频率的脉冲才能发声,仅给一个高电平或者低电平是不能发声的,因此蜂鸣器模块电路直接将STM32引脚接在NPN三极管的基极上, 然后三极管的发射极连接蜂鸣器,无需考虑外界对 PB5 脚产生的高低电平会对蜂鸣器发声干扰。如果使用的是有源蜂鸣器,它只要有电源就会发声,因此就必须考虑外界对 PB5 引脚电平的干扰问题。通过电阻 R06 和 PNP 三极管 TP6 进行电流放大,从而驱动蜂鸣器。电阻 R66 是一个上拉电阻, 用来防止蜂鸣器误发声。 当 PB5 引脚输出低电平时, PNP三极管导通,蜂鸣器发声;当 PB5 引脚输出高电平时,PNP 三极管截止,蜂鸣器停止发声。

7 ]" S2 E7 g2 [! u. B
软件设计
蜂鸣器初始化函数
    打开工程中 beep.c 文件,里面代码如下:
  1. #include "beep.h"/ J& k4 T, H- B9 y# }8 V

  2. ( a- b/ B& U" d2 c2 V% f
  3. /****************************************************************
    ; [+ e5 W* @: m% D3 C
  4. 4 v! b1 o$ q% V( z/ c: ]! ~9 l
  5. ***************
    1 q* b% y' c$ M* H- a/ Q- l, h

  6. : g% A8 b: q- ~( R6 z
  7. * 函 数 名 : BEEP_Init+ U8 p8 W9 B. |, T' n. h! y

  8. 6 x) k! o$ v. z0 k
  9. * 函数功能 : 蜂鸣器初始化+ e% o+ P5 ^/ E% ~8 g4 U# N* M7 \
  10. 9 l4 s, T) U3 Y: j6 n
  11. * 输 入 : 无
    7 p0 n: I* [& {, [( n. u
  12. 8 q- |2 b; M% }% e. x# G
  13. * 输 出 : 无
    ; Y  A8 u; n3 q! G

  14. 3 Z0 O- J0 A) v1 q8 H. V' Z
  15. ****************************************************************/
    0 c% D; m# x/ `
  16. ) W7 Q# Z5 [" P. M$ q: Q: _
  17. void BEEP_Init() //端口初始化! c& V6 P6 x6 @% A

  18. ; U2 Q  }2 Z6 j* g2 G0 X
  19. {
    + p* O* Z* [; u* \- f, F. T- J

  20. ! S! P+ d  [* b" Y; U  s- Z( `! S, D
  21. GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化 GPIO7 u/ D2 n# V  N6 q5 ^
  22. ) o/ c% A! J% t0 [- `6 L  ^
  23. RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE); /* 开启 GPIO 时钟 */
      S2 H% Z- u7 O- C8 y

  24. 5 i4 |+ Q! Y& D: W: \& A& E; B
  25. /* 配置 GPIO 的模式和 IO 口 */" i! F' v! q7 G& S+ \2 o
  26. 6 ?9 s0 |' Y! e3 J
  27. GPIO_InitStructure.GPIO_Pin=BEEP_PIN; //选择你要设置的 IO口
      C% q0 B5 I4 A7 k- s" \9 z" o
  28. ) W3 X" X3 r! l1 Y5 K
  29. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
    : A+ y3 r1 ~  O; R8 J- x- `$ K2 R7 R

  30. ; ]1 V: M. i1 {" n9 B
  31. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
    3 J! w. s4 N+ v: R& k

  32. " Y, |8 J  k: ?0 A
  33. GPIO_Init(BEEP_PORT,&GPIO_InitStructure); /* 初始化 GPIO*/3 R) v/ i0 `. n, J" s- u
  34. 4 g1 Z' r* }5 _* L: G
  35. }
复制代码

- ~7 m# t2 ]' w( l- k
    BEEP_Init()函数用来初始化蜂鸣器的端口及时钟,在函数内我们看到有几个参数不是库函数内的,比如 BEEP_PIN、BEEP_PORT、BEEP_PORT_RCC,这种情况一般是我们自己定义的宏,通常放在对应的头文件内,我们打开 beep.h,可以看到如下代码:
  1. #ifndef _beep_H
    # z- f" N5 o; s' g
  2. # y3 ]+ O+ U* W, q* ^* b# o1 G
  3. #define _beep_H
    # W- w* m+ M4 I! [' q& f. i: r+ @$ O

  4. / N( M* N% G  ]1 k6 v
  5. #include "system.h"
    & q. L$ _9 _* ]  |- g

  6. ! K. x- B' p9 T
  7. /* 蜂鸣器时钟端口、引脚定义 */
    0 A2 f! ?5 p% S

  8. 9 ^& f0 G; i! z- [: _8 G" f! x
  9. #define BEEP_PORT GPIOB6 p9 h5 c7 [* V# M1 n# v4 \
  10. ; S' B2 E3 v* H( j* r
  11. #define BEEP_PIN GPIO_Pin_5
    ; `  `$ g$ H' L) K0 F* Q

  12. 3 S& B8 i, J" m$ z# G1 l4 {  u
  13. #define BEEP_PORT_RCC RCC_APB2Periph_GPIOB
    ( C! j! }- L$ i
  14. # o6 ^/ o6 E9 u/ `: g
  15. #define beep PBout(5)
    5 B7 J: ^  h5 |

  16. ! ~8 w" G9 h1 i5 h5 C- d
  17. void BEEP_Init(void);& |! E: v$ ^7 u4 D

  18. ( `; B3 i. l0 n
  19. #endif
复制代码

) w0 X. r; t% ~6 ?
    里面就将蜂鸣器的GPIO 端口及管脚进行了宏定义,这样做是方便大家移植程序,只需要对这个宏修改就能实现蜂鸣器的初始化修改。

! W( G. Y" |! u$ r+ m
主函数
    我们打开工程中 main.c 文件,里面代码如下:
  1. /****************************************************************
    0 c; T1 @: B6 J
  2. : K! D- W- ?; ~( r1 T# s
  3. * 函 数 名 : main
    $ W( }: m' Y& w4 @$ ~. b. W

  4. % m+ }4 X" R9 W$ \
  5. * 函数功能 : 主函数
    7 j& n- t( A: V: J, e. Y
  6. - z* f7 i! _; E
  7. * 输 入 : 无& ]7 k6 ^1 T7 z1 M* U1 w
  8. 1 z. L# k! X' i% `* v
  9. * 输 出 : 无
    * z9 [8 M$ r5 U( ^6 f% i4 y8 o

  10. # Z: E; o, s$ p! t
  11. ****************************************************************/
    $ c0 ^; u- ^2 Z3 y4 g7 o* y6 ?
  12. ' w# a9 [$ D" N' e  q
  13. int main()
    ( a5 F4 K: G7 G! X, F1 S
  14. 2 d  z1 V# n+ o; a) U8 X
  15. {& }# n* Q% E3 {& V$ u

  16.   q. ?3 W) G; ^/ z
  17.     u16 i=0;
    ' l! F" t4 y5 r& S* m. U, z

  18. / T( I5 u! `0 m& V
  19.     SysTick_Init(72);
    1 }6 L$ p3 S' t, [; K" g4 F

  20. . {0 g5 w, g0 Q
  21.     LED_Init();
    ! @0 [, l7 I+ [  y

  22. 8 b% }; w& W& Z  g9 A
  23.     BEEP_Init();. ^" t# d- V5 j- p

  24. ! p/ Z/ D2 ]6 c; Y, a# w5 ~+ \# |
  25.     while(1)
      [7 r4 [1 [0 b* F  W

  26. " x3 F3 A& R/ ?+ R4 k+ F) Y
  27.     {2 B% E* a# Z9 e% y

  28. & P9 k3 F; ]$ Z( u" w% h
  29.         i++;0 h. r: r" Y8 N" R
  30. ) j" P+ o7 T( N; F4 r
  31.         if(i%10==0)4 }: _5 }% n; w4 c% [  f  p4 ?
  32. * @. I) {; e7 Z' f* y+ o; k
  33.         {
    - {7 J# e9 w- P
  34. 5 _9 V: M: ^+ Z
  35.             beep=!beep;% a+ V/ U5 @0 \+ O

  36. , N6 w9 y- P  I( h/ M( F' M
  37.         }
    * s; K5 N, L6 w/ M1 T& H

  38. ' V0 L9 W3 ]8 |1 ?8 i
  39.         if(i%20000==0)
    9 R* n" e# W, Z# V; Z4 V
  40. 9 o- W) O; [# {0 ~. a+ S
  41.         {
    ) Y+ [' b; C( {& L+ h

  42. 1 [& j) q" K5 X2 Y8 C+ c6 M
  43.             led1=!led1;4 c6 l2 }8 ?, {! N( C5 v- x

  44. / K- R6 i$ u: U6 ^
  45.         }0 L% Q- ~& b% S' ?4 N) k4 ^

  46. 9 c/ h- H* R; f
  47.         delay_us(10);  f2 v4 K/ l* o

  48. 4 i* C9 }. o: ]+ {2 W; i  ^5 r
  49.     }
    , ~# T9 i# ^9 v! o* m! S
  50. " l. L1 A5 j/ D9 _; |
  51. }
复制代码
  X2 e. @  r3 B  {" I
    主函数实现的功能比较简单,首先将使用到的外设硬件进行初始化,然后进入 while 循环,间隔 100us 对蜂鸣器管脚电平翻转,这样就产生了一个频率为5KHz 的脉冲,因此无源蜂鸣器就会发声,当然有源蜂鸣器的控制可以更简单,只需要给它一个低电平即可,为了实现 2 块板子程序的兼容,这里就统一采用此种方式控制蜂鸣器。间隔 200ms 对 led1 管脚电平翻转,因为使用到了 delay_us延时函数,所以在 main 函数开始处就需要调用 SysTick_Init(72)初始化,这个在我们后面所有程序都会使用,后面就不重复。
    将工程程序编译下载到开发板内,可以看到 D1 指示灯间隔 200ms 闪烁,蜂鸣器发声。
# W) Z  `2 ~7 K6 T$ l. w4 o% }
收藏 评论0 发布时间:2022-7-1 12:25

举报

0个回答

所属标签

相似分享

官网相关资源

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