上一节我们学习了LED的一些有趣的实验,这节我们换一种外设——蜂鸣器,蜂鸣器是一种常见的发声器件,电子产品等设备经常会配备蜂鸣器作为声音指示器。


文章目录

  • 蜂鸣器是什么
  • 无源蜂鸣器工作原理
  • 实验代码
  • 编译+烧录
  • 实验效果
  • 有源蜂鸣器代码


  • 先简单介绍本文将用到的硬件及软件:
    硬件平台:普中51开发板-单核A2
    软件:Keil5(C51)、STC-ISP(或其他ISP软件)、Proteus8.9(用于仿真,非必须)

蜂鸣器是什么

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。比如台式电脑的主机开机会"滴"一声、洗衣机按下按键及洗衣完成都会有声响,以上这些声音都是通过蜂鸣器来发出的。

下图是蜂鸣器的电路图形符号(蜂鸣器也是有正负极之分的)

protues让蜂鸣器发声 protues蜂鸣器在哪_引脚


蜂鸣器按驱动方式可分为有源蜂鸣器(内含驱动线路)和无源蜂鸣器(外部驱动)。这里的“”指的是激励源。

无源蜂鸣器内部没有激励源,只有给它一定频率的方波信号,才能让蜂鸣器的振动装置起振,从而实现发声,同时,输入的方波频率不同,发出的声音也不同(所以无源蜂鸣器可以模拟曲调实现音乐效果)。

有源蜂鸣器则不需要外部的激励源,只需要接入直流电源,即可自动发出声音(声音频率相对固定)。

由于有源蜂鸣器较为简单,只需要单片机给出高低电平即可控制其工作发声(还需借助三极管放大电路),这和上两节讲的LED很类似,所以本节就不重点讨论有源蜂鸣器(但文末有简单代码介绍),只研究单片机如何控制无源蜂鸣器。


无源蜂鸣器工作原理

protues让蜂鸣器发声 protues蜂鸣器在哪_51单片机_02


无源蜂鸣器需要1.5~2.5kHz(与蜂鸣器种类有关)的音频信号,这个音频信号即一个高低变化频率为1.5-2.5kHz的方波。实际上频率小于1.5kHz也是有声音的,只是不那么准了,可能是嘟嘟声。

实验代码

在写代码前,我们需要先创建一个Keil工程,创建工程的步骤已经在本系列第一篇文章中讲述。这里就不进行赘述。

前面提到无源蜂鸣器需要一定频率的高低变化的信号才能驱动发声,那么怎么用代码产生一个高低变化的信号(方波)呢?

和上节所讲的呼吸灯一样,我用到了模拟PWM,void Simulate_Pwm(unsigned char period, unsigned char duty)实现了类似PWM输出的功能,period为周期,控制整个过程的时间长度(对应蜂鸣器的频率,频率=1/周期),duty表示低电平时间占周期时间的比例,在这个实验里,这个值对蜂鸣器影响不大(选择50%即可)。

#include <reg52.h>   //此文件中定义了单片机的一些特殊功能寄存器


sbit beep = P1^5;	 //定义蜂鸣器的引脚

/******************************************************************************
 * @ 函数名  : Delay_10us
 * @ 功  能  : 10us粗略延时
 * @ 参  数  : 延时时间--单位10us
 * @ 返回值  : 无
 ******************************************************************************/
void Delay_10us(unsigned int time)
{
	while(time--);
}
 
 /******************************************************************************
 * @ 函数名  : Simulate_Pwm
 * @ 功  能  : 模拟PWM控制(需要不停运行)
 * @ 参  数  : period 周期(单位10us)
 *              duty   占空比(低电平,0-100)
 * @ 返回值  : 无
 ******************************************************************************/
void Simulate_Pwm(unsigned char period, unsigned char duty)
{
	unsigned char low = period / 100 * duty; //低电平延时时间
	unsigned char high = period - low;       //高电平延时时间
		
	beep = 0;        //蜂鸣器IO电平置低
	Delay_10us(low); //低电平延时时间
		
	beep = 1;        //蜂鸣器IO电平置高
	Delay_10us(high);//高电平延时时间
		
}

/******************************************************************************
 * @ 函数名  : main
 * @ 功  能  : 主函数
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/

int main()
{
	
	while(1)
	{
		//使用模拟PWM控制蜂鸣器
		Simulate_Pwm(100, 50);  //周期100*10us,占空比50%——频率:1KHz
	}
	
}
  • reg52.h:<reg52.h>表示你调用了52或者51单片机的资源,也就是可以直接对单片机的相关寄存器与引脚进行操作,里面涉及和很多内容,这里只要知道它是一个必须加的一个头文件即可。
  • sbit beep = P1^5;sbit是定义特殊功能寄存器的位变量(bitsbit都是C51扩展的变量类型,即C51特有的,而不是C语言标准变量类型),这里我们只需要把sbit当成一个类型即可,就像char、int,只不过char指的是一个字节,而sbit指的是字节里的一个位。
    上面还提到特殊功能寄存器(SFR),SFR是80C51单片机中各功能部件对应的寄存器,用于存放相应功能部件的控制命令,状态或数据,SFR(sfr)也是一种扩充数据类型,占用一个内存单元(1字节)。上面式子中的P1就是一个SFR,在reg52.h中,定义了P1寄存器的地址,如果我们对P1进行赋值,就等同于对51单片机的特殊功能寄存器赋值,即P1对应的8个IO端口。
    知道了sbitP1的含义,那么理解sbit beep = P1^5;就不难了,即定义P1.5引脚的状态为beepP1^5也是C51的特有用法,表示P1的第5位数据。
  • while(1){}:这是一个死循环,由于单片机上电后要不停的工作,所以我们不能让main函数结束,而是让它不停地执行while函数内部的工作。
  • Simulate_Pwm(100, 50);:上面已经提过了,用于模拟PWM输出,可以让蜂鸣器IO输出一定频率的方波(第二个参数需要选50),方波频率由函数第一个参数决定,当第一个参数(period)为100时,对应的频率为1/(100*10us)=1KHz

编译+烧录

程序编写完成后,接下来的操作就是编译+烧录了,这些步骤已经在本系列第一篇文章中讲述。不过这里还是会简单描述一下操作过程:

  • 点击编译按钮,如果怕出现意外,可以点第三个(重新编译),编译完成后Build Output窗口会显示报错信息,如果没有错误和警告(如果这几行都有警告,那说明有问题),且生成了hex文件,说明编译成功。

protues让蜂鸣器发声 protues蜂鸣器在哪_51单片机_03

  • 将刚才生成的hex文件烧录到单片机中,即可听到蜂鸣器在响了。

protues让蜂鸣器发声 protues蜂鸣器在哪_寄存器_04

实验效果

  • 实际效果:(实际效果就不方便展示了)
  • 仿真效果:上电后蜂鸣器响起。
    【Proteus软件的安装和使用可以参考我的另一篇博客(带安装包下载链接)

protues让蜂鸣器发声 protues蜂鸣器在哪_单片机_05


有源蜂鸣器代码

这里简单介绍一下有源蜂鸣器的控制代码:
功能:让有源蜂鸣器以500ms的间隔进行鸣叫

#include <reg52.h>   //此文件中定义了单片机的一些特殊功能寄存器


sbit beep = P1^5;	 //定义蜂鸣器的引脚

/******************************************************************************
 * @ 函数名  : Delay_10us
 * @ 功  能  : 10us粗略延时
 * @ 参  数  : 延时时间--单位10us
 * @ 返回值  : 无
 ******************************************************************************/
void Delay_10us(unsigned int time)
{
	while(time--);
}
 

/******************************************************************************
 * @ 函数名  : main
 * @ 功  能  : 主函数
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/

int main()
{	
	while(1)
	{
		beep = ~beep;       //高低电平切换
		Delay_10us(50000);  //延时约500ms
	}
}

仿真效果:

有源蜂鸣器以大约500ms的间隔进行鸣叫

【Proteus软件的安装和使用可以参考我的另一篇博客(带安装包下载链接)

protues让蜂鸣器发声 protues蜂鸣器在哪_51单片机_06