单片机之蜂鸣器
蜂鸣器是一种常见的发声元器件,广泛应用于各种电子产品,用于警报或报警处理,家里的洗衣机、微波炉、闹钟、遥控车、计算器等都会用到蜂鸣器。
目录
蜂鸣器介绍
前言:蜂鸣器是一种常见的发声元器件,广泛应用于各种电子产品,用于警报或报警处理,家里的洗衣机、微波炉、闹钟、遥控车、计算器等都会用到蜂鸣器。
蜂鸣器的分类
发声原理分类
按有源无源分类
- 有源蜂鸣器:内部自带震荡源,将正负极接上直流电压即可持续发声,频率固定。
- 无源蜂鸣器:内部不带震荡源,需要控制器提供震荡脉冲才可发声,调整提供震荡脉冲的频率,可发出不同频率的声音(单片机使用的就是无源蜂鸣器)
注意:无源蜂鸣器不能一直给他通电,你必须给他交流电让他震荡他才能发声。
三极管驱动
前言:单片机的IO接口也是不足以驱动蜂鸣器,也需要外接一些驱动电路(蜂鸣器的功率稍微大些)。
注意:
- 对于上面的电路中,该蜂鸣器使用的是电磁式蜂鸣器,采用5V供电。
- 三极管驱动原理:利用了三极管的放大特性(类似外包)。
- 蜂鸣器左边的为续流管,因为该蜂鸣器是一个电感型蜂鸣器,电感元件在电流发生变化时都会产生反向电动势来尽力的维持电流不变(该反向电动势不会立即消失),当电源断开时也会产生反向电动势,该续流管的作用就是构成反向电动势的回路来消耗掉这个反向电动势以保护三极管电路不被击穿(理解:上面电源推三家管,下面电感拉三极管会导致穿透)
蜂鸣器原理
前言:通过交流电使蜂鸣器震荡进而发出声音,不同频率波形使蜂鸣器的震荡频率不同,然而物体的震动形成声音,声音的音调取决于震荡的频率,因此我们只需要给出不同频率的波形(通过定时器形成)让蜂鸣器按照不同频率震荡,那么蜂鸣器就可发出不同调子的声音。
音符与频率对照表
注意:
- 中音1就相当于钢琴的中央C。
- 钢琴键盘上的每个声音频率满足12均分律(隔12个声音,频率变成2倍)
蜂鸣器播放130.8Hz的声音
30.8Hz表示每秒钟会震动130.8次,那么震动一次需要1/130.8=0.0076452s;因为单片机的单位为微秒,所以为7645微秒;因为7645us为整个周期的值,所以还需除以2得到3822.6us(3823us为正电平或负电平持续的时间,整个周期时长7645us);因此我们只需要通过定时器输出频率为7645微秒的方波即可。
仿真案例
蜂鸣器发声
需求:我们想要蜂鸣器发出C(频率130.8Hz)的调子
电路图
keil文件
#include "reg51.h"
sbit sound=P2^0;
void inittimer(){
TMOD=0x01; //0000 0001——工作方式2
TH0=(65536-3823)/256;
TL0=(65536-3823)%256;
ET0=1;
EA=1;
TR0=1;
sound=0;
}
void main()
{
inittimer();
while(1);
}
void timer_isr() interrupt 1
{
TH0=(65536-3823)/256;
TL0=(65536-3823)%256;
sound=~sound;
}
注意:也可以用延时函数,每隔一段时间电平值取反,那么周期就是两倍的延时时间。
蜂鸣器播放音乐
需求:使用蜂鸣器播放歌曲孤勇者。
歌曲数据获得
- 音调:通过绘制不同频率的方波来实现。
- 节拍:通过延时函数来实现。
注意:该图片为下面数组三位数的表现形式
使用的频率
电路图:和上面的电路图一样。
keil文件
#include "reg51.h"
sbit sound=P2^0;
unsigned int timer,index=0; //定时器初值,数据表索引
unsigned char beat,num; //节拍数,21音的计数
//每个数的3个位数代表了不同的意义(音高,音长,音符)
code unsigned char gequ[]={
120,116,117,211,212,117,211,221,
211,117,211,212,117,211,221,211,212,213,212,213,212,223,
213,212,223,225,223,116,117,211,212,117,211,221,211,117,
211,212,117,211,221,211,212,213,212,213,212,223,213,212,
223,225,223,225,233,215,233,215,213,215,216,213,225,225,
233,215,233,215,213,215,216,213,225,215,215,213,212,222,
222,211,213,213,212,222,222,211,211,146,110,215,215,213,
212,222,222,211,213,213,212,222,222,211,211,146,140,0};
//频率表
code unsigned int pinlv[]={
466,523,587,659,698,784,880, //低音
923,1047,1175,1319,1568,1760, //中音
1865,2094,2351,2633,2792,3134,3517 //高音
};
//延时节拍数
void delay(unsigned char t){
unsigned int i=0,j=0;
for(i=t;i>0;i--){
for(j=23000;j>0;j--);
}
}
void play(){
while(gequ[index]){ //声音索引为0就停止播放
if(gequ[index]%10==0){ //若根据数据分离出来的音符是0表示不发声比如120
TR0=0;
}else{
num=gequ[index]%10+(gequ[index]/100-1)*7-1; //根据数据索引计算频率索引
timer=65535-(12000000/12)/(pinlv[num]*2); //根据频率计算初值
TH0=timer/256;
TL0=timer%256;
TR0=1;
}
beat=gequ[index]/10%10;
delay(beat); //延时的程序让你有足够的空间在特定的频率不断震荡,同时也起节拍的作用
index++; //声音索引自动+1
}
TR0=0; //播放结束停止定时器
index=0; //播放结束声音数据索引清零
}
void main()
{
sound=0;
TMOD=0x01;
EA=1;
ET0=1;
while(1){
//不断播放音乐,单曲循环
play();
}
}
void timer0() interrupt 1
{
TH0=timer/256;
TL0=timer%256;
sound=~sound;
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)