9

51单片机入门(4)蜂鸣器(无源+有源)

 2 years ago
source link: https://blog.csdn.net/weixin_43772810/article/details/121868520
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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

蜂鸣器是什么

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

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

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

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

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

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

我之前写过一篇文章详细介绍蜂鸣器,里面介绍了蜂鸣器的种类和一些简单的硬件知识,感兴趣的可以看看,传送门:🚀(点我)

无源蜂鸣器工作原理

在这里插入图片描述
无源蜂鸣器需要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文件,说明编译成功。

在这里插入图片描述

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

在这里插入图片描述

  • 实际效果:(实际效果就不方便展示了)

  • 仿真效果:上电后蜂鸣器响起。

请添加图片描述

有源蜂鸣器代码

这里简单介绍一下有源蜂鸣器的控制代码:
功能:让有源蜂鸣器以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的间隔进行鸣叫

请添加图片描述


如果文章对你有帮助,请留下你的点赞吧👍,这是我继续更新的最大动力🚀。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK