单片机的蜂鸣器演奏 生日歌

作者&投稿:系逄 (若有异议请与网页底部的电邮联系)
这是一个利用89C52RC单片机蜂鸣器演奏生日快乐歌。请高手帮我解释一下:整体思想,再在每一步添加注释。~

#include
sbit speaker=P1^6;
unsigned char timer0h,timer0l,time;
//生日歌,这三个字节一组,分别定义:旋律(1234567)、高低音(低音、中音、高音)、节奏(长度)
code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
// 音阶频率表 高八位,也就是发音对应频率的高八位
code unsigned char FREQH[]={0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;
// 音阶频率表 低八位,也就是发音对应频率的低八位
code unsigned char FREQL[]={0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16, };
void delay(unsigned char t) //延时程序
{
unsigned char t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{ ; } }
TR0=0;
}
void t0int() interrupt 1 //定时器0中断服务程序,控制声音打频率
{ TR0=0;
speaker=!speaker;
TH0=timer0h;
TL0=timer0l;
TR0=1;
}
void song() //启动演奏当前频率
{ TH0=timer0h; //当前频率的高八位
TL0=timer0l; //当前频率的低八位
TR0=1; //启动定时器0
delay(time); //延时当前频率的演奏时间
}
void main(void)
{
unsigned char k,i;
TMOD=1; //置CT0定时工作方式1 EA=1; ET0=1;//IE=0x82 //CPU开中断,CT0开中断
while(1)
{
i=0;
while(i<75)
{ //音乐数组长度 ,唱完从头再来
k=sszymmh[i]+7*sszymmh[i+1]-1; //取当前节奏的频率地址
timer0h=FREQH[k]; //取当前频率高八位
timer0l=FREQL[k]; //取当前频率低八位
time=sszymmh[i+2]; //取当前频率的时长
i=i+3; //三个字节一组
song(); //演奏当前频率,共75/3,25个曲调。
}
}
}
//程序的设计思路就是将一首乐曲分成三个变量来控制,分别是曲调、所在音区、时长。而控制曲调的因素也就是频率又分成高八位和第八位两个表,每演奏一个曲调,就根据该曲调的三个变量来取值。

#include
sbit speaker=P1^2;
unsigned char timer0h,timer0l,time;
//生日歌
code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
// 音阶频率表 高八位
code unsigned char FREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
} ;
// 音阶频率表 低八位
code unsigned char FREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
void delay(unsigned char t)
{
unsigned char t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{
;
}
}
TR0=0;
}
void t0int() interrupt 1
{
TR0=0;
speaker=!speaker;
TH0=timer0h;
TL0=timer0l;
TR0=1;
}
void song()
{
TH0=timer0h;
TL0=timer0l;
TR0=1;
delay(time);
}

void main(void)
{
unsigned char k,i;
TMOD=1; //置CT0定时工作方式1
EA=1;
ET0=1;//IE=0x82 //CPU开中断,CT0开中断
while(1)
{
i=0;
while(i<75){ //音乐数组长度 ,唱完从头再来
k=sszymmh[i]+7*sszymmh[i+1]-1;
timer0h=FREQH[k];
timer0l=FREQL[k];
time=sszymmh[i+2];
i=i+3;
song();
}
}
}

你一个分也没给,不想给你说,还是做下好人吧!
要想用模拟歌声首先要定义1234567不同的音符,做个h文件放这里,,你后做其他的歌曲可以共享。这里网上可以找到,我给你一个。。然后建立个歌曲主程序,根据歌谱子,结合你的音符定义给他他编码,把编的码放到一个数组里面然后输出就好了,,下面我给你一首歌作为例子,,我也没做个你那个什么生日歌,你自己去编码吧,,有谱子很好编码的
/**************************************************************************

SOUND PLAY FOR 51MCU

COPYRIGHT (c) 2005 BY JJJ.
-- ALL RIGHTS RESERVED --

File Name: SoundPlay.h
Author: Jiang Jian Jun
Created: 2005/5/16
Modified: NO
Revision: 1.0

*******************************************************************************/

/*说明**************************************************************************
曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)

音高由三位数字组成:
个位是表示 1~7 这七个音符
十位是表示音符所在的音区:1-低音,2-中音,3-高音;
百位表示这个音符是否要升半音: 0-不升,1-升半音。

音长最多由三位数字组成:
个位表示音符的时值,其对应关系是:
|数值(n): |0 |1 |2 |3 | 4 | 5 | 6
|几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n
十位表示音符的演奏效果(0-2): 0-普通,1-连音,2-顿音
百位是符点位: 0-无符点,1-有符点

调用演奏子程序的格式
Play(乐曲名,调号,升降八度,演奏速度);
|乐曲名 : 要播放的乐曲指针,结尾以(0,0)结束;
|调号(0-11) : 是指乐曲升多少个半音演奏;
|升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;
|演奏速度(1-12000): 值越大速度越快;

***************************************************************************/
#ifndef __SOUNDPLAY_H_REVISION_FIRST__
#define __SOUNDPLAY_H_REVISION_FIRST__

//**************************************************************************

#define SYSTEM_OSC 12000000 //定义晶振频率12000000HZ
#define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//每4分音符间隔
sbit BeepIO = P3^7; //定义输出管脚

unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };
unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存
//**************************************************************************
void InitialSound(void)
{
BeepIO = 0;
Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值 (10ms的初装值)
Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TMOD |= 0x11;
ET0 = 1;
ET1 = 0;
TR0 = 0;
TR1 = 0;
EA = 1;
}

void BeepTimer0(void) interrupt 1 //音符发生中断
{
BeepIO = !BeepIO;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
//**************************************************************************
void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
unsigned int NewFreTab[12]; //新的频率表
unsigned char i,j;
unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表
{
j = i + Signature;
if(j > 11)
{
j = j-12;
NewFreTab[i] = FreTab[j]*2;
}
else
NewFreTab[i] = FreTab[j];

if(Octachord == 1)
NewFreTab[i]>>=2;
else if(Octachord == 3)
NewFreTab[i]<<=2;
}

SoundLength = 0;
while(Sound[SoundLength] != 0x00) //计算歌曲长度
{
SoundLength+=2;
}

Point = 0;
Tone = Sound[Point];
Length = Sound[Point+1]; // 读出第一个音符和它时时值

LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
LDiv4 = LDiv0/4; // 算出4分音符的长度
LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
TR0 = 0;
TR1 = 1;
while(Point < SoundLength)
{
SL=Tone%10; //计算出音符
SM=Tone/10%10; //计算出高低音
SH=Tone/100; //计算出是否升半
CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
if(SL!=0)
{
if (SM==1) CurrentFre >>= 2; //低音
if (SM==3) CurrentFre <<= 2; //高音
Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
Sound_Temp_TH0 = Temp_T/256;
Sound_Temp_TL0 = Temp_T%256;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
}
SLen=LengthTab[Length%10]; //算出是几分音符
XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
FD=Length/100;
LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
if (FD==1)
LDiv=LDiv+LDiv/2;
if(XG!=1)
if(XG==0) //算出普通音符的演奏长度
if (SLen<=4)
LDiv1=LDiv-LDiv4;
else
LDiv1=LDiv*SOUND_SPACE;
else
LDiv1=LDiv/2; //算出顿音的演奏长度
else
LDiv1=LDiv;
if(SL==0) LDiv1=0;
LDiv2=LDiv-LDiv1; //算出不发音的长度
if (SL!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //发规定长度的音
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; BeepIO=0;
for(i=LDiv2;i>0;i--) //音符间的间隔
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
Point+=2;
Tone=Sound[Point];
Length=Sound[Point+1];
}
BeepIO = 0;
}
//**************************************************************************
#endif

同一首歌编码输出
#include <REG52.H>
#include "SoundPlay.h"

void Delay1ms(unsigned int count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}

//*****************************Music******************************************************

//同一首歌
unsigned char code Music_Same[]={ 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x66, 0x18,0x03,
0x17,0x02, 0x15,0x02, 0x16,0x01, 0x15,0x02, 0x10,0x02,
0x15,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x02,
0x17,0x03, 0x18,0x03, 0x19,0x02, 0x15,0x02, 0x18,0x66,
0x17,0x03, 0x19,0x02, 0x16,0x03, 0x17,0x03, 0x16,0x00,
0x17,0x01, 0x19,0x02, 0x1B,0x02, 0x1B,0x70, 0x1A,0x03,
0x1A,0x01, 0x19,0x02, 0x19,0x03, 0x1A,0x03, 0x1B,0x02,
0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x18,0x66, 0x18,0x03,
0x19,0x02, 0x1A,0x02, 0x19,0x0C, 0x18,0x0D, 0x17,0x03,
0x16,0x01, 0x11,0x02, 0x11,0x03, 0x10,0x03, 0x0F,0x0C,
0x10,0x02, 0x15,0x00, 0x1F,0x01, 0x1A,0x01, 0x18,0x66,
0x19,0x03, 0x1A,0x01, 0x1B,0x02, 0x1B,0x03, 0x1B,0x03,
0x1B,0x0C, 0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x1F,0x01,
0x1A,0x01, 0x18,0x66, 0x19,0x03, 0x1A,0x01, 0x10,0x02,
0x10,0x03, 0x10,0x03, 0x1A,0x0C, 0x18,0x0D, 0x17,0x03,
0x16,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x70,
0x18,0x03, 0x17,0x02, 0x15,0x03, 0x15,0x03, 0x16,0x66,
0x16,0x03, 0x16,0x02, 0x16,0x03, 0x15,0x03, 0x10,0x02,
0x10,0x01, 0x11,0x01, 0x11,0x66, 0x10,0x03, 0x0F,0x0C,
0x1A,0x02, 0x19,0x02, 0x16,0x03, 0x16,0x03, 0x18,0x66,
0x18,0x03, 0x18,0x02, 0x17,0x03, 0x16,0x03, 0x19,0x00,
0x00,0x00 };

//***********************************************************************************
main()
{
InitialSound();
while(1)
{
Play(Music_Girl,0,3,360);
Delay1ms(500);
Play(Music_Same,0,3,360);
Delay1ms(500);
Play(Music_Two,0,3,360);
Delay1ms(500);
}
}

也不难 找到生日歌的谱子然后再编进单片机内

去买个音乐贺卡,拆下来,藏于单片机的下面,哦也,搞定


西吉县18858855947: 求: 用51单片机c语言操作使蜂鸣器奏出“祝你生日快乐”音乐的全部程序!
哀欣凯络: #include <reg51.h> sbit speaker=P1^2; unsigned char timer0h,timer0l,time; //生日歌 code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4, 5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4, 5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2, 4,2,1, 4,2,...

西吉县18858855947: 单片机的蜂鸣器演奏 生日歌 -
哀欣凯络: 你一个分也没给,不想给你说,还是做下好人吧! 要想用模拟歌声首先要定义1234567不同的音符,做个h文件放这里,,你后做其他的歌曲可以共享.这里网上可以找到,我给你一个..然后建立个歌曲主程序,根据歌谱子,结合你的音符定...

西吉县18858855947: 哪位好心人给我一个51单片机C语言让蜂鸣器唱生日歌的程序啊,谢谢啦!! -
哀欣凯络: //此程序在硬件上调试通过//本程序的单片机晶振采用11.0592M#include <reg51.h> sbit speaker=P1^2; unsigned char timer0h,timer0l,time; //生日歌 code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4, 5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2...

西吉县18858855947: 用89C51单片机和蜂鸣器播放“ 生日快乐”歌的C程序 12M晶振
哀欣凯络: #include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit BEEP=P2^6; void Music(uchar number); void delay10us(uchar time); void delay50us(uchar time); uchar code SOUNDLONG[]= //控制音调 { 18,6,24,24,24,48, 18,6,24,24,...

西吉县18858855947: 如何使用msp430f6638单片机播放两只老虎和生日歌 -
哀欣凯络: 有两种方法: 一、用脉冲控制蜂鸣器频率来模仿音谱,把需要的哥曲转换成脉冲频率的值, 二.用语音芯片,把哥烧录进语音芯片,然后用单片机控制播放即可. 说明:第一种 需要对单片了解得相对深入些,第二种很简单,会控制单片机IO就可以了. WT588语音芯片就能实现,具体要看你的板子的尺寸和安装位置是否充足.第一种适合空间小的场景,如果对于板子尺寸要求不严格,第二种 方法会快得多,但成本相对会高一些.

西吉县18858855947: 哪位好心人给我一个51单片机C语言让蜂鸣器唱生日歌的程序啊,谢谢啦!!
哀欣凯络: <p>//此程序在硬件上调试通过</p> <p>//本程序的单片机晶振采用11.0592M</p> <p>#include <reg51.h></p> <p>sbit speaker=P1^2; </p> <p>unsigned char timer0h,timer0l,time;</p> <p> //生日歌</p> <p>code unsigned char sszymmh[]={5,1,1, 5,1,...

西吉县18858855947: 求单片机播放生日歌的C程序? -
哀欣凯络: 主要原理就是用sound (频率);这个函数发出指定频率的声音,再用delay(时间);这个函数来使声音保持一定时间. ********************************************************************** 程序: #include <stdlib.h> #include <stdio.h> #include <dos.h>...

西吉县18858855947: 用单片机奏出生日快乐歌
哀欣凯络: 如果对你有用,请采纳! /* 名称:播放音乐 说明:程序运行时播放生日快乐歌, 未使用定时器中断,所有频率完全用延时实现 */ #include&lt;reg51.h&gt; #define uchar unsigned char #define uint unsigned int sbit BEEP=P3^7; //生日快乐歌的音...

西吉县18858855947: 单片机音乐程序怎么编,用C语言编,比如说编一首生日快乐或者爱的供养,应该怎么弄 -
哀欣凯络: 这个需要用无源的蜂鸣器,然后改变输出的信号的频率来达到一定的音阶,先制作基本的音符,然后拼成一首歌.

西吉县18858855947: 如何使用51单片机的蜂鸣器来播放某些歌曲? -
哀欣凯络: 蜂鸣器的发声频率是固定的,不能改变声调.要播放歌曲的话最好用小喇叭,通过改变脉冲的频率可以控制小喇叭的声调.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网