找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15536|回复: 2
收起左侧

STM32蜂鸣器实例详解-日志之总结篇2

[复制链接]
ID:136256 发表于 2017-3-16 02:30 | 显示全部楼层 |阅读模式
//======================================================//

**基于STM32的蜂鸣器实例详解
//======================================================//
在学习蜂鸣器实验前,先来看看什么是蜂鸣器,蜂鸣器又有哪些种类。下面看看百度是怎么描述蜂鸣器的。

//===========================百度搜索===========================//
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“ZZG”、“LB”、“JD”等)表示。

结构原理:
1.电压式蜂鸣器 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。有的压电式蜂鸣器外壳上还装有发光二极管。
多谐振荡器由晶体管或集成电路构成。当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
压电蜂鸣片由锆钛酸铅或铌镁酸铅压电陶瓷材料制成。在陶瓷片的两面镀上银电极,经极化和老化处理后,再与黄铜片或不锈钢片粘在一起。
2.电磁式蜂鸣器 电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

分类:有源蜂鸣器和无源蜂鸣器
//======================================================//

首先说明一下,所谓的有源跟无源不是说是否有没有带电源,这里的有源是指带有震荡电路,带有震荡电路的蜂鸣器的特点就是一通电就会发声。无源蜂鸣器则没有自带震荡电路,必须外部提供2~5kHZ的方波来驱动,才能发声。

无源蜂鸣器的优点是:
1. 便宜
2. 声音频率可控,可以做出“多来米发索拉西”的效果
3. 在一些特例中,可以和LED复用一个控制口
有源蜂鸣器的优点是:程序控制方便。

一般情况下,开发板上都会采用有源蜂鸣器,那么伴随着一个问题就是是否直接把有源蜂鸣器直接接在单片机的GPIO上就能响呢?其实不然,在讨论这个问题时,我们要明确单片机的GPIO最大可以提供的电流是多少?有源蜂鸣器的驱动电流又要多少?
答案:单片机有很多种,这里就只说STM32F1系列的其中一款STM32F103ZET6,STM32F103ZET6这款芯片的单个GPIO最大可以提供的电流在25mA左右,当然不同的单片机其GPIO的驱动电流不尽相同,会有所差别,这个数据可以直接从IC的数据手册上查到。而蜂鸣器的驱动电流是30mA左右,相比之下,两个电流值相当接近,那么是否就可以驱动起来呢?我们全盘考虑一下,STM32F1整个芯片的电流,最大才150mA,如果直接驱动的话,其他GPIO的电流就得相应降下一定值,也就是说,其他GPIO就会出现供电不足的不稳定状态,所以在这种情况下,一般就会在驱动电路上考虑问题。也就是既然不能在单片机GPIO上直接驱动,那是否可以考虑用驱动电路来使得GPIO以一个较小的值来驱动蜂鸣器呢?答案也是一定的,可以。一般在单片机上不用GPIO直接驱动蜂鸣器,而是通过一个三极管扩流后再驱动蜂鸣器,这样就可以使单片机的GPIO只需要接近1mA的电流,就可以驱动蜂鸣器。
下面放一个蜂鸣器的驱动电路图:
0.png

0.png
不同的厂家,不同单片机上的驱动电路会有稍微不同。


图中我们用到一个NPN三极管(S8050)来驱动蜂鸣器,R33主要用于防止蜂鸣器的误发声。当PB.8输出高电平的时候,,蜂鸣器将发声,当 PB.8 输出低电平的时候,蜂鸣器停止发声。
蜂鸣器的使用,跟跑马灯的使用,方法是一样的,也是通过对相应的寄存器,来实现GPIO的输出控制,BEEP在就直接代表PB8的输出状态。(我的开发板蜂鸣器接在PB8上,如上面的驱动电路图所示,不同的开发板会有所不同)。我们只需要控制ODR寄存器的高低电平,就可以实现蜂鸣器的控制。
代码如下:
//=======================beep.c===============================//
#include "stm32f10x.h"

void beep_Init(void)
{
RCC ->APB2ENR |= 1 << 3;//使能 PORTE 时钟

GPIOB ->CRH   |= 3 << 0;//先设置输出模式
GPIOB ->CRH   &=~ (3 << 2);//PB.8 推挽输出
GPIOB ->ODR   &= ~(1 << 8);//PB.8 输出低
}
//======================================================//
注释:首先也是使能PB组的GPIO时钟,这是必不可少的,然后就是设置PB8为输出模式,再设置通用推挽输出。这里设置ODR为低电平目的是为了,程序运行时蜂鸣器处于关闭状态。
==================================华丽的分界线=================================
//===========================beep.h===========================//
/************************************************
接口:BEEP引脚接在 PB8 高电平有效
************************************************/
#ifndef __BEEP_H_
#define __BEEP_H_

extern void beep_Init(void);

#endif

//======================================================//
==================================华丽的分界线=================================
//==========================main.c============================//
/*******************************************************
**功能:实现两个LED亮同时蜂鸣器响,然后延时,LED灭,蜂鸣器关
**
********************************************************/
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "beep.h"
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
      delay_init(72); //延时初始化
led_Init();//LED初始化
beep_Init();
while(1)
{

GPIOB ->ODR   &= ~ (1 << 5);//PB.5输出低电平,即点亮LED
GPIOE ->ODR   &= ~(1 << 5); //PB.5输出低电平,即点亮LED
GPIOB ->ODR   |= (1 << 8);      //PB.8 输出高,即蜂鸣器开
delay_ms(10000);    //延时

GPIOB ->ODR   |= 1 << 5;//PE.5输出高电平,即灭掉LED
GPIOE ->ODR   |= 1 << 5;//PB.5输出高电平,即灭掉LED
GPIOB ->ODR   &= ~(1 << 8);     //PB.8 输出低,即蜂鸣器关
delay_ms(10000);    //延时

}
}
//======================================================//
注释:这里调用了,STM32的一个库,也就是调用了delay_ms()函数,要使得delay_ms()函数有效,要使能系统时钟,也就是要先初始化Stm32_Clock_Init(9)跟delay_init(72)。Stm32_Clock_Init()函数和delay_init()函数我会新开一篇来讲述,现在简单的说一下,它的作用,delay_init(72)设置系统时钟的频率,Stm32_Clock_Init(9)是设置倍频。这里稍作了解就行了。

当然不使用delay_ms(),也是可以的,修改如下
注释掉
//======================================================//
#include "sys.h"
#include "delay.h"
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
//======================================================//
然后把delay_ms(10000)修改成for(i=0;i<1000000;i++)延时也是可以的。(不要忘了声明 int i=0;)
延时函数可按照个人习惯自己使用自己喜欢或常用的函数。
==================================华丽的分界线=================================

//=======================================================================//
注释:1、如有错误,跪谢大神出来指错。
2、如这篇文章对您有些帮助,转载请注明出处,谢谢!
//=======================================================================//



评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:544005 发表于 2020-2-19 14:57 | 显示全部楼层
不错不错谢谢分享
回复

使用道具 举报

ID:475858 发表于 2021-3-23 15:10 | 显示全部楼层
总结非常详细
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表