做个实际的项目,总有某些时候需要出点声音的,例如键盘按下后就要来个‘D’的声音,其实单片机发个声音是很简单的,IO,电阻,三极管,蜂鸣器,就可以了。这里以DX板上的发声系统为硬件基础:
WWW_PLC※JS_COM-PmLC-技.术_网
这个设计和普通的蜂鸣器有点不同,其实就是为了让P17可以免除干扰地复用作ISP口。平时P17为低电平,可以省电。
WW.W_PLCJS_COM-PLC-技.术_网
这里需要说明一下的,这些小小的两个脚的蜂鸣器,表面上个个一样,但实际上是分两种的,一种是通电就会响,另外一种是只能通过脉冲发声。通电响的那种用做普通发声设备,发出单纯的声音,简单方便。脉冲式的使用上没那么方便,但发出的各频率的声音都比较悦耳的。DX51学习板上用的就是脉冲式的了,所以平时P17是高是低,它都不会响。
P.L.C.技.术.网——可编程控制器技术门户
以下是DX学习板上的普通发声程序:WWW_PL※CJS_COM-PLC-技.术_网
sbit BB=P1^7;
WW.W_PLCJS_COM-PLC-技.术_网
void beep(uchar t)P_L_C_技_术_网——可——编——程——控-制-器-技——术——门——户
{WW.W_PLC※JS_C,OM-PL,C-技.术_网
uchar i;W1WW_P4LCJS_COM-PLC-技.术_网
uint j;WWW.PLCJS.COM——可编程控制器技术门户
for(j=0;j<t*256;j++)WWW.PLCJS.COM——可编程控制器技术门户
{WWW_PLCJS※COM-PLC-技×术_网(可编程控※制器技术门户)
for(i=100;i>0;i--);//给i赋的初值决定输出的频率WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
BB=~BB;WWW.PLCJS.COM——可编程控制器技术门户
}WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
}WWW※PLCJS_COM-PL#C-技.术_网(可编※程控※制器技术门户)
由于是脉冲形式的,所以发声就是通过一个取反BB=~BB;完成。上面的程序很简单,t决定了发声时间,i的初值决定了发声频率。频率是多少可以通过指令周期的计算得到,但个人觉得这类单声的东东,还是用耳朵听,多试几个频率值,方能找到我们最满意的频率:)
——可——编——程——控-制-器-技——术——门——户
如果要产生几个音调,可以写多几组不同时间长短和不同频率的代码,简单的我们从上面的代码修改:
WWW_P※LCJS_CO※M-PLC-技-.术_网
sbit BB=P1^7;plcjs.技.术_网
void beep(uchar t)WWW※PLCJS_COM-PL#C-技.术_网(可编※程控※制器技术门户)
{WWW_PLCJS※COM-PLC-技×术_网(可编程控※制器技术门户)
uchar i;WWcW_PLCJS_COM-PLC-技.术_网
uint j;WWW.PLCJS.COM——可编程控制器技术门户
//第一声——可——编——程——控-制-器-技——术——门——户
for(j=0;j<t*256;j++)P_L_C_技_术_网——可——编——程——控-制-器-技——术——门——户
{WWW_PL※CJS_COM-PLC-技.术_网
for(i=100;i>0;i--);WWW_PLC※JS_COM-PmLC-技.术_网
BB=~BB;WWW_PLCJS_COM-PLC-技.术_网
}WWW.PLCJS.COM——可编程控制器技术门户
WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
for(j=0;j<t*100;j++); 这个是两个声音之间的时间间隔WWW_PLCJS_COM-PLC-技.术_网
WWW_PLCJ-S_COM-PLC-技.术_网(可-编程控-制器技术-门户)
//第二声WWW_PLCJS※COM-PLC-技.术_网(可※编程控※制器技术门户)
for(j=0;j<t*200;j++) P.L.C.技.术.网——可编程控制器技术门户
{WW.W_PLCJS_COM-PLC-技.术_网
for(i=150;i>0;i--);WWW_PLCJ-S_COM-PLC-技.术_网(可-编程控-制器技术-门户)
BB=~BB;WWW_PLCJ-S_COM-PLC-技.术_网(可-编程控-制器技术-门户)
}WWW_PLCJS※COM-PLC-技.术_网(可※编程控※制器技术门户)
plcjs.技.术_网
}P.L.C.技.术.网——可编程控制器技术门户
程序很简单,就是发了一声后,延迟一定时间再发第二声.大家可以试着写段自己的代码,听听声音效果.
WWW_PLCJS@_COM%-PLC-技.术_网
但上面的程序是用延时发声的,当你要发出很长的声音的时候,延时部分就会占用了所有CPU资源,也就是在发声过程中我们什么都做不了,当然对于一般的响应声音,例如按键后发出声音,程序应付有余,但对于其它用途,这种方法就显得效率很低了。这里介绍一中用定时器的方法实现的声#include "reg51.h"
WWW※PLCJS_COM-PL#C-技.术_网(可编※程控※制器技术门户)
#define uchar unsigned char
WWW.PLCJS.COM——可编程控制器技术门户
sbit BB=P1^7; //蜂鸣器控制脚
WWW_P※LCJS_COM-PLC-)技.术_网
uchar beep_flag=0; //发声标志WWW_PLCJS※COM-PLC-技×术_网(可编程控※制器技术门户)
uchar count_time=0; //中断计数WWW※PLCJS_COM-PL#C-技.术_网(可编※程控※制器技术门户)
void initTimer(void)
WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
{WW.W_PLCJS_COM-PLC-技.术_网
TMOD=0x1;WWcW_PLCJS_COM-PLC-技.术_网
TH0=0xe0;WWcW_PLCJS_COM-PLC-技.术_网
TL0=0xc6;WWW_PL※CJS_COM-PLC-技.术_网
}W1WW_P4LCJS_COM-PLC-技.术_网
void timer0(void) interrupt 1
WWW.PLCJS.COM——可编程控制器技术门户
{plcjs.技.术_网
TH0=0xe0;WW.W_PLCJS_COM-PLC-技.术_网
TL0=0xc6;WWW_P※LCJS_CO※M-PLC-技-.术_网
if(!beep_flag)P_L_C_技_术_网——可——编——程——控-制-器-技——术——门——户
{P_L_C_技_术_网——可——编——程——控-制-器-技——术——门——户
count_time=0;WWW_PLC※JS_COM-PmLC-技.术_网
}WWW_PL※CJS_COM-PLC-技.术_网
elseW1WW_P4LCJS_COM-PLC-技.术_网
{WW.W_PLC※JS_C,OM-PL,C-技.术_网
count_time++;WWW_P※LCJS_CO※M-PLC-技-.术_网
BB=~BB;plcjs.技.术_网
if(count_time>70)WWW_PLCJS※COM-PLC-技×术_网(可编程控※制器技术门户)
{WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
count_time=0;WW.W_PLC※JS_C,OM-PL,C-技.术_网
beep_flag=0;WWW_PLC※JS_COM-PmLC-技.术_网
}WWW_PLCJS_COM-PLC-技.术_网
}
WW.W_PLC※JS_C,OM-PL,C-技.术_网
}
WWW_PLC※JS_COM-PmLC-技.术_网
WWW_PLC※JS_COM-PLC-技.术_网(可编程控※制器技术门户)
void main(void)
WWW※PLCJS_COM-PL#C-技.术_网(可编※程控※制器技术门户)
{WW.W_PLCJS_COM-PLC-技.术_网
initTimer();W1WW_P4LCJS_COM-PLC-技.术_网
TR0=1;WW.W_PLCJS_COM-PLC-技.术_网
ET0=1;P.L.C.技.术.网——可编程控制器技术门户
EA=1;W1WW_P4LCJS_COM-PLC-技.术_网
beep_flag=1;WWW_PLCJS※COM-PLC-技×术_网(可编程控※制器技术门户)
while(1);WWW_PLCJS※COM-PLC-技.术_网(可※编程控※制器技术门户)
}WWcW_PLCJS_COM-PLC-技.术_网
plcjs.技.术_网
WWcW_PLCJS_COM-PLC-技.术_网
——可——编——程——控-制-器-技——术——门——户
上面程序有着大家已经熟悉的count_time变量,其实它就是用来控制发声时间长短的,而定时时间(取决于TH,TL)就是用来产生频率的。可能初学者第一次看这样的程序有一点点迷惑也说不定,但只要用心去想想,几分钟后大家就能明白。说透了,定时器中断函数是会不断地执行的,但对于函数中的BB=~BB;这一句,就只会在 beep_flag=1;之后运行一段时间——这段时间取决于count_time 要计时多长,count_time>70后就计算完,此时清除beep_flag=0;那么count_time++; BB=~BB;就不会再运行了。WW.W_PLCJS_COM-PLC-技.术_网