单片机蜂鸣器问题 请大虾举个简单例子来说明如何实现发出不同音调的音乐
看起来数组应该是音乐数据,其中包括四种数据,就是休止符(每个100毫秒)、歌曲结束符、音阶(给出的是蜂鸣器的震荡周期)、一个音阶持续的时间长度。如果你的晶振是12MHz,按照定时器中断给Count加一来看,音阶持续的时间应该是以10毫秒为单位。
Play_Song函数要求给出参数i,我的看法是这个i是指要播放第几段乐曲,i*217表示每段乐曲都是217个字节。本例中,数组只给出217个字节,所以只有一段乐曲,播放时需要给出参数i=0.
if ( Temp1 == 0xFF ) //休止符
{
TR0 = 0;
Delay_xMs(100);
}
所以休止符每个固定是100毫秒。
如果读到第一个不是休止符或者结束符的字节,那就是音阶,而下一个字节就是这个音阶的长度或者说节拍
while(1)
{
FMQ = ~FMQ;
Delay_xMs(Temp1);
if ( Temp2 == Count )
{
Count = 0;
break;
}
}
这一段是说,如果当前音阶的时间(Temp2次定时器中断,由Count计时)还没完,就每隔Temp1毫秒震动一次蜂鸣器,就形成一个震动频率,这段时间就发出一定音调的乐音。不过我也有疑惑,震荡周期如果以毫秒为单位恐怕只能发出次声波,所以以上对有关Delay_xMs函数时间的估算都可能有问题,还得看Delay_xMs函数的具体定义才行。
我这里有现成的程序,把分给我,留下信箱,我就给你发过去,呵呵。我利用软件定时和中断方式都有,可以演奏音乐,不过蜂鸣器演奏的实在够难听。
看来楼主对程序不感兴趣,我还是告诉你吧,你定时必须知道准确的定时时间,音乐中DO RE MI-----SI都是有一定的频率也就是Hz,都如下:
c1:262Hz--thtl=0xf8b3
d1:294Hz--0xf972
e1:330Hz--0xfa14
f1:349Hz--0xfa66
g1:392Hz--0xfb03
a1:440Hz--0xfb8f
b1:494Hz--0xfc0b
前面是HZ,后面是我用硬件定时得到的TH和TL的值。
比如你想发C1的音,先用软件定一个262*2Hz的延时反复调用,在一个周期内使buzzer响,再接着一个周期使buzzer不响,如此反复就得到了262Hz的声音,也就类似发出了C1的声音。
反正是够难听的。
这个主要用定时器1CTC模式,启动iv_TIMER1_COMPA中断,然后得到一定的歌曲平率参数就可以搞定。我搜到个程序,如下;
/****************************************
* 用M16单片机I/O口生成模拟音乐 *
* 功 能:用I/O口生成模拟音乐 *
* 时钟频率:外部7.3728M *
* 设 计:tonghe *
* 修改日期:2007年04月13日 *
* 编译环境:ICC-AVR6.31 *
* 实验环境:阿发的M16学习板 *
* 发 声:无源蜂鸣器接于PD5 *
* 结 果:试验通过 *
****************************************/
#include <iom16v.h>
#include <macros.h>
#include "wo_ni.h" //包含音乐文件
#include "delay.h" //延时文件
#define uchar unsigned char
#define uint unsigned int
/************************************
* 端口初始化函数 *
************************************/
void port_init(void)
{
PORTD=0x20; //蜂鸣器接口初始化为高
DDRD=0x20; //蜂鸣器接口为输出
}
/**********************************
*定时器1中断入口函数:产生方波发声*
**********************************/
#pragma interrupt_handler timer1:iv_TIMER1_COMPA
void timer1(void) //定时器1中断入口
{
PORTD^=(1<<5); //产生方波,发声
}
/***********************************
* 音乐产生函数 *
* 功能:输出频率为x的方波,延时y MS*
* 范围:x:100-20000Hz,0:不发声 *
* y:0-65536 MS *
***********************************/
void sound(uint i)
{
uint x;
x=i; //取音乐的频率数据
if(x!=0)
{
x=3686400/x; //数据计算
OCR1A=x; //比较值赋值
TCCR1B = 0x09; //允许比较反转输出
}
else
{
TCCR1B = 0x00; //频率为0,休止符,不发声
}
}
/******************************
* 主函数 *
******************************/
void main(void)
{
uchar i=0;
port_init();
TCCR1A = 0x40; //将T/C1配置为CTC模式,OC1A取反:产生音乐
TIMSK |= (1<<OCIE1A); //开启比较匹配中断
SEI(); //开总中断
while(1)
{
TCCR1B = 0x09; //开启比较匹配
while(music_data[i][1]!=0) //等待最后一个音符到来
{
sound(music_data[i][0]); //输出音符
delay_ms(music_data[i][1]);//节拍延时
TCCR1B = 0x00; //奏完一个音符停止
PORTD|=(1<<5); //关闭蜂鸣,保护喇叭
i++; //准备一下个音符
delay_ms(5); //演奏
}
TCCR1B = 0x00;
PORTD|=(1<<5); //关闭蜂鸣,保护喇叭
delay_ms(4000);
i=0;
}
}
//////头文件2
flash unsigned int music_data[][2]=
{
{587,800},{698,800},{466,1600},{523,800},{587,800},{349,1600},
{466,800},{523,800},{587,800},{698,800},{523,3200},{587,800},
{698,800},{466,1600},{523,800},{587,800},{392,1600},{523,800},
{349,800},{523,800},{587,800},{466,1600},{784,1600},{698,1600},
{784,1600},{466,1600},{587,800},{392,800},{587,1200},{698,400},
{523,3200},{587,800},{698,800},{466,1600},{523,800},{587,800},
{392,1600},{523,800},{349,800},{523,800},{587,800},{466,3200},
{ 0, 0}
};
#pragma data:data
//头文件3
/****************************************
* 函数名称: void delay_us(uchar i) *
* 函数功能:延时函数 *
* 晶振频率:7.3728MHZ *
****************************************/
void delay_us(unsigned int i)
{
while(i--)
{
NOP();
NOP();
}
}
/****************************************
* 函数名称: void delay_ms(uint i) *
* 函数功能:延时函数 *
* 晶振频率:7.3728MHZ *
* 入口参数:i mS *
****************************************/
void delay_ms(unsigned int i)
{
unsigned int a;
for(;i;i--)
{
for(a=1052;a;a--)
{;}
}
}
你自己组合下这些程序,把PD5接蜂鸣器的接口。会很奇妙的。
有疑问联系
蜂鸣器分为两种,一种是有源的,一种是无源的。如果你想让蜂蜜器发出不同的音调,那你需要买那种有源的蜂鸣器,然后通过改变你给信号的频率,就可以改变发出的声音了。如果你买的是无源的,那么就只有一种音调。
得看你用的是什么样的蜂鸣器,有的是给电平就响的,有的是要给一定频率的脉冲;而后者才能发出不周的单调,当然方法就是让加上蜂鸣器上的频率不一样!
试试下列程序:
http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/d025718ab4fa7bdefc1f10b7.html
简于牛黄: 用蜂鸣器产生音乐很诡异.大家都知道,单片机上的蜂鸣器都是加高低电平后,才有声音的.从理论上来说,声音是不具有频率,音色,等.对于单片机来说,用一个IO口的高低电平变化来产生的不同平率带动蜂鸣器产生各种生音事可以实现的...
广安市18641598409: 各位大虾有没有低电平驱动蜂鸣器响的的电路 - ?
简于牛黄: 你一说,说明你单片机水平还比较低,哪有什么叫“低电平驱动蜂鸣器响”,蜂鸣器响是因为不停和输入了脉冲,脉冲就是由高低电平组成的,你给单片机单独输入低电平或高电平,它是不会响的
广安市18641598409: 我有一个C程序:想让它执行一次蜂鸣一次,但是系统执行太快,只能听到最后一次蜂鸣 - ?
简于牛黄: 如下:#include<stdio.h>#include <conio.h>#include <windows.h> // VC下#include <unistd.h> //GCC下这个头文件 main() { int a; for(a=0;a<=10;a++) { printf("voice%d\a\n",a); Sleep(1000); // 延迟1000毫秒 } getch(); }
广安市18641598409: 我不太理解单片机中断的试用,举个简单程序例子来讲解下.?
简于牛黄: 这个是定时器0的中断处理函数.当定时器定时时间到后就由硬件自动调用这个函数,执行完后返回原来断点. 你这个程序应该是让蜂鸣器发声的,定时时间由STH0,STL0来保存,时间到后,接蜂鸣器的I/O口反转一次.
广安市18641598409: S8050三极管驱动蜂鸣器 - ?
简于牛黄: 能,不过建议把蜂鸣器放在集电极
广安市18641598409: 跟晶振为12hz的51单片机p3口连接的三极管要用高频管还是低频管???,三极管是用来驱动蜂鸣器的????? - ?
简于牛黄: 低频,三极管的pnp,npn都可以.驱动蜂鸣器的话,甚至可以不用三极管直接驱动,将蜂鸣器的正极电位拉高就可以了
广安市18641598409: 请教各位大虾,用51单片机如何来实现和弦音? - ?
简于牛黄: 两个方波脉冲分别用一个口输出,把两个输出口连在一起不就叠加了
广安市18641598409: 单片机烧不进程序去了,一直显示请给MCU上电 - ?
简于牛黄: 不要说小白,任谁都是长期晒黑滴.你别着急,人忙无智,也许问题很简单.如果你的电路板上有大的电解电容器,断电以后,等长一点时间再上电烧录程序,目的是等电容器储存的电荷放掉.不然单片机不认为是冷启动.这样还不行,检查复位电路、晶振电路、烧写程序的连接电路,这些再没问题,换单片机吧.
广安市18641598409: 刚学单片机 有个简单的但我搞不清楚的问题请教各位大虾?
简于牛黄: 首先解释一下ACALL指令的操作过程:程序计数器内容先加2,指向下一条指令的地址,然后将PC值压入堆栈保存,栈指针SP加2;接着将11位目的地址(addr0~addr10)送程序计数器的低11位(PC0~PC10),PC值的高5位(PC11~PC15)...