玩过单片机的人,在初学用单片机驱动蜂鸣器发声的时候,会不会对为何能用简单的高低电平信号控制蜂鸣器发出不同的声音呢?如果您学过高等数学,这个发声的原理就很简单了。
我们都知道,人类正常可以听到的声音,本质上就是人耳可识别频率范围内的正弦波构成的。人耳可以听到的声波的频率一般在20kHz(赫兹)至2kHz之间。在声波的频率范围内,发声的频率决定着音调的高低:频率高,音调也高,声音尖锐;反之,频率低,音调也低,声音低沉。
用单片机控制IO发出方波是很容易的事情,对方波的傅里叶变换可知,一个方波是可以被看成石油不同频率的正弦波合成出来。如果在正弦波的频率是处于可识别声波的范围时,我们就能听到声音。
基于上面的知识点,我们可以使用51单片机通过IO口,配合蜂鸣器和不同的程序代码,模拟出几种常用的声音。
1、报警声
信号产生的方法:500Hz信号周期为2ms,信号电平为每1ms变反1次;1KHz 信号周期为1ms,信号电平每500us变反1次。
代码如下:
#include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int sbit BEEP = P1^4 ; //蜂鸣器 sbit FLASH=P1^0; sbit K1=P3^7; /********************************************************* 500us延时函数 晶振:11.0592MHz *********************************************************/ void delay500(void) { uchar i; for(i=230;i>0;i--); } main() { int j, i; P0=0x0; P1=0xff; P2=0xff; i = 3; while(1) { if (K1==1) { for(j=200;j>0;j--) { BEEP=~BEEP; //输出频率500Hz delay500(); //延时 delay500(); delay500(); delay500(); delay500(); } FLASH=~FLASH; i--; if (i < 1) { BEEP = 0; i = 3; for(j=1500;j>0;j--) { delay500(); //延时1ms delay500(); } } } } }
2、滴滴声
代码如下:
#include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int uchar Count1,Count2; bit flag; sbit K1 = P3^2 ; sbit K2 = P3^3 ; sbit BEEP = P1^4 ; //蜂鸣器 /******************************************************** 主函数 *********************************************************/ main() { P0=0X0; Count1=0x00; Count2=0x00; BEEP=1; flag=0; TMOD=0x01; TH0=0xfc; TL0=0x66; //1ms定时 EA=1; ET0=1; while(1) { if(K1==1) { TR0=1; } if(K1==0) { TR0=0; } } } /********************************************************* Time0中断函数 **********************************************************/ void Time0(void) interrupt 1 using 0 { TH0=0xfc; //1ms定时 TL0=0x66; Count1++; if(Count1==100) { Count2++; if(Count2==4) { Count1=0; Count2=0; flag=~flag; } } if(!flag) { BEEP=~BEEP; } }
以上代码中的Kn是使用IO接按钮,用来控制是否启动发声处理。
P1.4接蜂鸣器,要加上限流电阻。
三极管可以选用8550,也可以使用其它小功率PNP三极管。ULN2003也可以。
有兴趣的小伙伴可以动手试试。因为原理是通用的,在ARM单片机上也可以同样实现这个功能。