(1)实验平台:
普中STM32精灵开发板https://item.taobao.com/item.htm?id=739076227953(2)资料下载:普中科技-各型号产品资料下载链接
在前面章节中我们已经介绍了如何控制 STM32 的IO 口输出高低电平,本章我们通过另外一个实验来讲述 STM32 IO 口的输出。通过STM32F1 芯片的一个IO口控制板载无源蜂鸣器,实现蜂鸣器控制。学习本章可以参考《STM32F1xx 中文参考手册》 8 通用 I/O(GPIO)章节,或者参考前面 LED 实验章节。本章分为如下几部分内容:
13.1 蜂鸣器介绍
蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V 直流工作电压),多谐振荡器起振,输出 1.5~5kHZ 的音频信号,阻抗匹配器推动压电蜂鸣片发声。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
其实一句话就可概括它们之间的区别,要想压电式蜂鸣器发声,需提供一定频率的脉冲信号;要想电磁式蜂鸣器发声,只需提供电源即可。
我们开发板上使用的蜂鸣器是无源蜂鸣器,属于压电式蜂鸣器类型。这里说的有源无源,并不是指电源的意思,而是指蜂鸣器内部是否含有振荡电路,有源蜂鸣器内部自带振荡电路,只需提供电源即可发声,而无源蜂鸣器则需提供一定频率的脉冲信号才能发声,频率大小通常在 1.5-5KHz 之间。蜂鸣器实物图如下图所示:
如果给无源蜂鸣器加一个 1.5-5KHz 的脉冲信号会发声,而且改变这个频率,就可以调节蜂鸣器音调,产生各种不同音色、音调的声音。如果改变输出电平的高低电平占空比,则可以改变蜂鸣器的声音大小。
13.2 硬件设计
在前面章节中我们已经对 STM32 的 GPIO 做了简单介绍,并且还使用了其中IO 口直接控制开发板上的 LED。对于本章要实现蜂鸣器的控制,我们能否直接使用 STM32 的 IO 口驱动呢?根据 STM32F1 芯片数据手册可知,单个IO 口的最大输出电流是 25mA,而蜂鸣器的驱动电流是 30mA 左右,两者非常接近,有的朋友就想直接用 IO 口来驱动,但是有没有考虑到整个芯片的输出电流,整个芯片的输出电流最大也就 150mA,如果在驱动蜂鸣器上就耗掉了30mA,那么STM32 其他的IO 口及外设电流就非常拮据了。所以我们不会直接使用IO 口驱动蜂鸣器,而是通过外部驱动电路后再驱动蜂鸣器,这样 STM32 的 IO 口只需要提供不到1mA的电流就可控制蜂鸣器。所以我们也经常说到 STM32 芯片是用来做控制的,而不是驱动。
我们 STM32F1 开发板上的蜂鸣器模块电路如下图所示:
从电路图中可以看到,STM32 芯片的 PB0 引脚是用来控制蜂鸣器的,驱动电路 ULN2003 芯片 OUT5 管脚输出驱动蜂鸣器,ULN2003 芯片使用简单,输入为高电平,输出则为低电平,输入为低电平,输出则为高组态;输出低电平时蜂鸣器得到电压,高组态时,蜂鸣器断开,只要不断输出一定频率高低电平脉冲信号即可发出声音。
13.3 软件设计
我们打开“\4--实验程序\1--基础实验\7-蜂鸣器实验”工程,在APP 文件夹内可以看到又新建了一个 beep 文件夹,这个在前面LED 实验的时候也说过为什么要这样操作。
13.3.1 蜂鸣器初始化及报警函数
我们打开工程中 beep.c 文件,里面代码如下:
#include "beep.h"
#include "SysTick.h"
/*******************************************************************************
* 函 数 名 : BEEP_Init
* 函数功能 : 蜂鸣器初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void BEEP_Init(void) //端口初始化
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化GPIO
RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE); /* 开启GPIO时钟 */
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=BEEP_PIN; //选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
GPIO_Init(BEEP_PORT,&GPIO_InitStructure); /* 初始化GPIO */
GPIO_ResetBits(BEEP_PORT,BEEP_PIN);
}
//蜂鸣器报警
//times:报警次数
//us:延时微秒时间
void BEEP_Alarm(u8 times,u8 us)
{
while(times--)
{
BEEP=!BEEP;
delay_us(us);
}
}
BEEP_Init 函数用来初始化蜂鸣器的端口及时钟,在函数内我们看到有几个参数不是库函数内的,比如 BEEP_PIN、BEEP_PORT、BEEP_PORT_RCC,这种情况一般是我们自己定义的宏,通常放在对应的头文件内;
BEEP_Alarm 函数用来实现蜂鸣器报警,函数内有两个参数,times 为循环次数,us 为触发脉冲时间,通过传递不同的 us 值从而改变不同频率。
我们打开 beep.h,可以看到如下代码:
#ifndef _beep_H
#define _beep_H
#include "system.h"
/* 蜂鸣器时钟端口、引脚定义 */
#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_Pin_0
#define BEEP_PORT_RCC RCC_APB2Periph_GPIOB
#define BEEP PBout(0)
//函数声明
void BEEP_Init(void);
void BEEP_Alarm(u8 times,u8 us);
#endif
里面就将蜂鸣器的 GPIO 端口及管脚和端口时钟进行了宏定义,这样做是方便大家移植程序,只需要对这个宏修改就能实现蜂鸣器的初始化修改。假如你们自己做的板子,蜂鸣器放在 PA5 管脚上控制,那你只需要修改beep.h 头文件内容,把 RCC_APB2Periph_GPIOB 改为 RCC_APB2Periph_GPIOA,GPIOB 改为GPIOA,GPIO_PIN_8 改为 GPIO_PIN_5,把 PBout(8)改为 PAout(5),而beep.c 文件完全不用修改,是不是非常方便呢?
13.3.2 主函数
我们打开工程中 main.c 文件,里面代码如下:
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "beep.h"
int main()
{
SysTick_Init(72);
LED_Init();
BEEP_Init();
while(1)
{
LED0=!LED0;
BEEP_Alarm(100,100);
delay_ms(200);
}
}
主函数实现的功能比较简单,首先将使用到的外设硬件进行初始化,然后进入 while 循环,不断翻转 led 管脚状态,同时调用蜂鸣器报警函数,传递循环次数未 100,脉冲时间为 100us,因为使用到了 delay_ms 延时函数,所以在main函数开始处就需要调用 SysTick_Init(72)初始化,这个在我们后面所有程序都会使用,后面就不重复。
13.4 实验现象
将工程程序编译下载到开发板内,可以看到核心板上指示灯间隔200ms 闪烁一次,同时蜂鸣器发声一次。