首页 > 代码库 > [51单片机学习笔记TWO]----蜂鸣器

[51单片机学习笔记TWO]----蜂鸣器

蜂鸣器音乐播放实验

首先应该了解一下蜂鸣器音乐播放的原理,在这里我只讲一下电磁式蜂鸣器驱动原理(还有一种是压电式蜂鸣器):

电磁式蜂鸣器驱动原理:

  蜂鸣器发声原理是电流通过电磁线圈,使电磁圈产生磁场来驱动振动膜发声的。因此需要一定的电流才能驱动它,而单片机I/O引脚输出的电压较小。单片机输出的TTLK电平基本驱动不了蜂鸣器,因需要增加一个放大电路。这里用三极管作为放大电路。下面是原理图:

我这里的J8端是跟芯片的P1^5端口相连,当P1^5输出高电平时,三极管截止,蜂鸣器不发声,反之,输出低电平时,蜂鸣器发声。

而要驱动蜂鸣器能像唱歌一样的发声,其实只要使蜂鸣器发出频率和持续时间不同的声音即可。周期等于频率的倒数,所以可以通过频率知道这段的时间,所以可以通过调用延时函数或者定时器实现,同样的发声的持续时间也可以通过延时函数实现,所以让蜂鸣器唱歌最关键的就是知道要延长多少时间!

用单片机来演奏音乐,,只要搞清楚两个概念就好了,分别是“音调”和“节拍”。

音调表示一个音符该唱的频率。

节拍表示一个音符该唱多少时间。

这里有两种方法来实现该功能:

(1)查表法

这个方法复杂的地方在于你要找出每个音符相对应的频率(根据音符;频率对照表找),然后根据公式转换为相应的时间(取半周期),然后通过延时函数实现。最后编程实现。 

先上代码好了:

 1 /*************************************************** 2 实验名称:用蜂鸣器播放生日快乐歌 3 实验说明:不使用定时器中断,所有频率完全用延时实现 4 实验时间: 2014/12/5 5 ***************************************************/ 6  7 #include<reg51.h> 8 #define uchar unsigned char 9 #define uint unsigned int 10 11 sbit BEEP=P1^5;//蜂鸣器接芯片的P1^5端口12 13 /*生日快乐歌的音符频率表,不同频率由不同的延时来决定音符频率明显大于数组里面的值,但是因为是8位寄15 存器,所以最多只能放511,但是有的频率大于511,所以只能在延时函数中乘上相应的值来接近实际乐谱频率*/17 uchar code SONG_TONE[]=18 {212,212,190,212,159,169,212,212,190,212,142,159,212,19  212,106,126,159,169,190,119,119,126,159,142,159,0};20 21 //生日快乐歌节拍表,节拍决定每个音符的演奏长短,只是取个系数,并非准确的值22 uchar code SONG_LONG[]=23 {9,3,12,12,12,24,9,3,12,12,12,24,9,24  3,12,12,12,12,12,9,3,12,12,12,24,0};25 26 //延时27 void DelayMS(uint x)28 {29     uchar t;30     while(x--)31         for(t=0;t<120;t++);32 }33 34 //播放函数35 void PlayMusic()36 {37     uint i=0,j,k;38     while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)39         {40         /*播放各个音符,SONG_LONG为拍子长度,一个节拍大概为 400ms-500ms,这里的节拍又受下面一个音符的影响,所以只能根据大概的来取值*/41             for(j=0;j<SONG_LONG[i]*26;j++)42             {43                 BEEP=~BEEP;44                 //SONG_TONE延时表决定了每个音符的频率45                 for(k=0;k<SONG_TONE[i]/3;k++); 46             }47             48             DelayMS(50);49             i++;50         }51 }52 53 void main()54 {55     BEEP=0;56     while(1)57     {58         PlayMusic();//播放生日快乐59         DelayMS(500);//播放完后暂停一段时间60     }61 }

整个流程是这样的:

首先根据生日快乐歌的乐谱将各个音调转换为相应的频率。

比如:左边是生日快乐歌乐谱,右边是音符频率转换表

        

这里先来了解一下乐谱的一点知识,左边乐谱数字下面有点说明是低音,没点说明就是普通的,数字上面有点就是高音,而5的低音就是4.5,高音是5.5,其他音符也是相应的道理。

乐谱的左上方有写“1=F”,而一般的乐谱都是C调,就是“1=C”,注意,乐谱里面的1234567(哆啦咪发索拉西多)相对应的不是ABCDEFG而是CDEFGAB!所以这里规定是F调的话,

那么就说明2就要唱G,3要唱A,……7要唱E,所以这里的低音5对应的应该是低音的1.5!!!!就是所谓的要相应的左移或者右移。如果还是不明白的话,看下面:

1原本对应的应该是C,4原本应该对应的是F,对吧?

然后现在1对应的变成F了,就相当于对应了4,对吧?

那么1.5对应的是什么?

4.5咯!

那2对应的是什么?

5呗!

那么好了咯,低音5是4.5,是不是就是等于1.5?所以半周期就是1803µs。

至于为什么是根据半周期算,那是因为单片机是通过循环对蜂鸣器接的端口置位,复位来使发声的,所以就是半周期。因为我用的是无源的蜂鸣器,有源的蜂鸣器就是全周期了。

然后就是按照上述道理,一个个转换,并用延时函数实现,因为每个音符的转换频率都不一样,要么使用多个延时函数一个个实现准确的音调频率,但是这样太烦,而且单片机本身就不是专门

弄来唱歌的。我们不应该为难他们,所以自己将就一下就算了。所以延时函数为了适应每个音调都有差不多的频率,这个就靠自己计算了,而且不同的歌那个值还不一样,所以这就是这个问题

的难点。

接下来的就是那个唱多久的问题,一般的歌曲默认的一个节拍是400ms-500ms。

同样的看乐谱左上方,它有写“3/4”,意思是以四分音符为节拍,每一个小结有三拍。

而在每个数字下面有一条横线,那时间就是那个节拍的时间乘上0.5,有两条就乘上0.25,三条就乘以0.125。。。音乐的基本知识就别为难我了,我是个音乐白痴。。所以我就这么理解了。。

哈哈哈哈哈~

而至于节拍转换为频率,也是有相应的表的,见下:

同样的也是通过延时函数来实现,当然也是会有误差的。而至于延时函数怎么写,见[51单片机学习笔记ONE]

编程思想的话挺简单的,就是先将音符频率和所要唱的时间转换好,放到两个数组里面。然后在主程序里面,通过延时达到相应频率,唱完一遍,停一会,接着唱就好了。

(2)用工具转码并用计时器实现

先上代码好了:

  1 /*说明**************************************************************************    2  曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)    3    4  音高由三位数字组成:    5         个位是表示 1~7 这七个音符     6         十位是表示音符所在的音区:1-低音,2-中音,3-高音;    7         百位表示这个音符是否要升半音: 0-不升,1-升半音。    8      9  音长最多由三位数字组成:    10         个位表示音符的时值,其对应关系是:    11             |数值(n):  |0 |1 |2 |3 | 4 | 5 | 6    12             |几分音符: |1 |2 |4 |8 |16 |32 |64      音符=2^n   13         十位表示音符的演奏效果(0-2):  0-普通,1-连音,2-顿音   14         百位是符点位: 0-无符点,1-有符点   15   16  调用演奏子程序的格式   17         Play(乐曲名,调号,升降八度,演奏速度);   18     |乐曲名           : 要播放的乐曲指针,结尾以(0,0)结束;   19     |调号(0-11)       :   是指乐曲升多少个半音演奏;   20     |升降八度(1-3)    : 1:降八度, 2:不升不降, 3:升八度;   21     |演奏速度(1-12000): 值越大速度越快;   22   23 ***************************************************************************/   24 #ifndef __SOUNDPLAY_H_REVISION_FIRST__    25 #define __SOUNDPLAY_H_REVISION_FIRST__    26    27 #include <REG51.H>    28    29 //**************************************************************************    30    31 #define SYSTEM_OSC      11059200//12000000  //定义晶振频率12000000HZ    32 #define SOUND_SPACE     4/5         //定义普通音符演奏的长度分率,//每4分音符间隔    33 sbit    BeepIO    =     P1^5;       //定义输出管脚    34    35 unsigned int  code FreTab[12]  = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表    36 unsigned char code SignTab[7]  = { 0,2,4,5,7,9,11 };                                  //1~7在频率表中的位置    37 unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };                          38 unsigned char Sound_Temp_TH0,Sound_Temp_TL0;    //音符定时器初值暂存     39 unsigned char Sound_Temp_TH1,Sound_Temp_TL1;    //音长定时器初值暂存    40 //**************************************************************************    41 void InitialSound(void)    42 {    43     BeepIO = 1;    44     Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256;   // 计算TL1应装入的初值  (10ms的初装值)    45     Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;   // 计算TH1应装入的初值     46     TH1 = Sound_Temp_TH1;    47     TL1 = Sound_Temp_TL1;    48     TMOD  |= 0x11;    49     ET0    = 1;    50     ET1    = 0;    51     TR0    = 0;    52     TR1    = 0;    53     EA     = 1;    54 }    55    56 void BeepTimer0(void) interrupt 1   //音符发生中断    57 {    58     BeepIO = !BeepIO;    59     TH0    = Sound_Temp_TH0;    60     TL0    = Sound_Temp_TL0;    61 }    62 //**************************************************************************    63 void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)    64 {    65     unsigned int NewFreTab[12];     //新的频率表    66     unsigned char i,j;    67     unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;    68     unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;    69     for(i=0;i<12;i++)               // 根据调号及升降八度来生成新的频率表     70     {    71         j = i + Signature;    72         if(j > 11)    73         {    74             j = j-12;    75             NewFreTab[i] = FreTab[j]*2;    76         }    77         else   78             NewFreTab[i] = FreTab[j];    79    80         if(Octachord == 1)    81             NewFreTab[i]>>=2;    82         else if(Octachord == 3)    83             NewFreTab[i]<<=2;    84     }                                       85         86     SoundLength = 0;    87     while(Sound[SoundLength] != 0x00)   //计算歌曲长度    88     {    89         SoundLength+=2;    90     }    91    92     Point = 0;    93     Tone   = Sound[Point];      94     Length = Sound[Point+1];            // 读出第一个音符和它时时值    95         96     LDiv0 = 12000/Speed;                // 算出1分音符的长度(几个10ms)        97     LDiv4 = LDiv0/4;                    // 算出4分音符的长度     98     LDiv4 = LDiv4-LDiv4*SOUND_SPACE;    // 普通音最长间隔标准     99     TR0   = 0;   100     TR1   = 1;   101     while(Point < SoundLength)   102     {   103         SL=Tone%10;                                 //计算出音符    104         SM=Tone/10%10;                              //计算出高低音    105         SH=Tone/100;                                //计算出是否升半    106         CurrentFre = NewFreTab[SignTab[SL-1]+SH];   //查出对应音符的频率        107         if(SL!=0)   108         {   109             if (SM==1) CurrentFre >>= 2;        //低音    110             if (SM==3) CurrentFre <<= 2;        //高音   111             Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值   112             Sound_Temp_TH0 = Temp_T/256;    113             Sound_Temp_TL0 = Temp_T%256;    114             TH0 = Sound_Temp_TH0;     115             TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿    116         }   117         SLen=LengthTab[Length%10];  //算出是几分音符   118         XG=Length/10%10;            //算出音符类型(0普通1连音2顿音)    119         FD=Length/100;   120         LDiv=LDiv0/SLen;            //算出连音音符演奏的长度(多少个10ms)   121         if (FD==1)    122             LDiv=LDiv+LDiv/2;   123         if(XG!=1)      124             if(XG==0)               //算出普通音符的演奏长度    125                 if (SLen<=4)       126                     LDiv1=LDiv-LDiv4;   127                 else  128                     LDiv1=LDiv*SOUND_SPACE;   129             else  130                 LDiv1=LDiv/2;       //算出顿音的演奏长度    131         else  132             LDiv1=LDiv;   133         if(SL==0) LDiv1=0;   134             LDiv2=LDiv-LDiv1;       //算出不发音的长度    135         if (SL!=0)   136         {   137             TR0=1;   138             for(i=LDiv1;i>0;i--)    //发规定长度的音    139             {   140                 while(TF1==0);   141                 TH1 = Sound_Temp_TH1;   142                 TL1 = Sound_Temp_TL1;   143                 TF1=0;   144             }   145         }   146         if(LDiv2!=0)   147         {   148             TR0=0; BeepIO=1;   149             for(i=LDiv2;i>0;i--)    //音符间的间隔   150             {   151                 while(TF1==0);   152                 TH1 = Sound_Temp_TH1;   153                 TL1 = Sound_Temp_TL1;   154                 TF1=0;   155             }   156         }   157         Point+=2;    158         Tone=Sound[Point];   159         Length=Sound[Point+1];   160     }   161     BeepIO = 1;   162 }   163 //**************************************************************************   164 #endif   165   166   167   168 //挥着翅膀的女孩   169 unsigned char code Music_Girl[]={ 0x17,0x02, 0x17,0x03, 0x18,0x03, 0x19,0x02, 0x15,0x03,   170                                   0x16,0x03, 0x17,0x03, 0x17,0x03, 0x17,0x03, 0x18,0x03,   171                                   0x19,0x02, 0x16,0x03, 0x17,0x03, 0x18,0x02, 0x18,0x03,   172                                   0x17,0x03, 0x15,0x02, 0x18,0x03, 0x17,0x03, 0x18,0x02,   173                                   0x10,0x03, 0x15,0x03, 0x16,0x02, 0x15,0x03, 0x16,0x03,   174                                   0x17,0x02, 0x17,0x03, 0x18,0x03, 0x19,0x02, 0x1A,0x03,   175                                   0x1B,0x03, 0x1F,0x03, 0x1F,0x03, 0x17,0x03, 0x18,0x03,   176                                   0x19,0x02, 0x16,0x03, 0x17,0x03, 0x18,0x03, 0x17,0x03,   177                                   0x18,0x03, 0x1F,0x03, 0x1F,0x02, 0x16,0x03, 0x17,0x03,   178                                   0x18,0x03, 0x17,0x03, 0x18,0x03, 0x20,0x03, 0x20,0x02,   179                                   0x1F,0x03, 0x1B,0x03, 0x1F,0x66, 0x20,0x03, 0x21,0x03,   180                                   0x20,0x03, 0x1F,0x03, 0x1B,0x03, 0x1F,0x66, 0x1F,0x03,   181                                   0x1B,0x03, 0x19,0x03, 0x19,0x03, 0x15,0x03, 0x1A,0x66,   182                                   0x1A,0x03, 0x19,0x03, 0x15,0x03, 0x15,0x03, 0x17,0x03,   183                                   0x16,0x66, 0x17,0x04, 0x18,0x04, 0x18,0x03, 0x19,0x03,   184                                   0x1F,0x03, 0x1B,0x03, 0x1F,0x66, 0x20,0x03, 0x21,0x03,   185                                   0x20,0x03, 0x1F,0x03, 0x1B,0x03, 0x1F,0x66, 0x1F,0x03,   186                                   0x1B,0x03, 0x19,0x03, 0x19,0x03, 0x15,0x03, 0x1A,0x66,   187                                   0x1A,0x03, 0x19,0x03, 0x19,0x03, 0x1F,0x03, 0x1B,0x03,   188                                   0x1F,0x00, 0x1A,0x03, 0x1A,0x03, 0x1A,0x03, 0x1B,0x03,   189                                   0x1B,0x03, 0x1A,0x03, 0x19,0x03, 0x19,0x02, 0x17,0x03,   190                                   0x15,0x17, 0x15,0x03, 0x16,0x03, 0x17,0x03, 0x18,0x03,   191                                   0x17,0x04, 0x18,0x0E, 0x18,0x03, 0x17,0x04, 0x18,0x0E,   192                                   0x18,0x66, 0x17,0x03, 0x18,0x03, 0x17,0x03, 0x18,0x03,   193                                   0x20,0x03, 0x20,0x02, 0x1F,0x03, 0x1B,0x03, 0x1F,0x66,   194                                   0x20,0x03, 0x21,0x03, 0x20,0x03, 0x1F,0x03, 0x1B,0x03,   195                                   0x1F,0x66, 0x1F,0x04, 0x1B,0x0E, 0x1B,0x03, 0x19,0x03,   196                                   0x19,0x03, 0x15,0x03, 0x1A,0x66, 0x1A,0x03, 0x19,0x03,   197                                   0x15,0x03, 0x15,0x03, 0x17,0x03, 0x16,0x66, 0x17,0x04,   198                                   0x18,0x04, 0x18,0x03, 0x19,0x03, 0x1F,0x03, 0x1B,0x03,   199                                   0x1F,0x66, 0x20,0x03, 0x21,0x03, 0x20,0x03, 0x1F,0x03,   200                                   0x1B,0x03, 0x1F,0x66, 0x1F,0x03, 0x1B,0x03, 0x19,0x03,   201                                   0x19,0x03, 0x15,0x03, 0x1A,0x66, 0x1A,0x03, 0x19,0x03,   202                                   0x19,0x03, 0x1F,0x03, 0x1B,0x03, 0x1F,0x00, 0x18,0x02,   203                                   0x18,0x03, 0x1A,0x03, 0x19,0x0D, 0x15,0x03, 0x15,0x02,   204                                   0x18,0x66, 0x16,0x02, 0x17,0x02, 0x15,0x00, 0x00,0x00};   205 //同一首歌   206 unsigned char code Music_Same[]={ 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x66, 0x18,0x03,   207                                   0x17,0x02, 0x15,0x02, 0x16,0x01, 0x15,0x02, 0x10,0x02,   208                                   0x15,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x02,   209                                   0x17,0x03, 0x18,0x03, 0x19,0x02, 0x15,0x02, 0x18,0x66,   210                                   0x17,0x03, 0x19,0x02, 0x16,0x03, 0x17,0x03, 0x16,0x00,   211                                   0x17,0x01, 0x19,0x02, 0x1B,0x02, 0x1B,0x70, 0x1A,0x03,   212                                   0x1A,0x01, 0x19,0x02, 0x19,0x03, 0x1A,0x03, 0x1B,0x02,   213                                   0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x18,0x66, 0x18,0x03,   214                                   0x19,0x02, 0x1A,0x02, 0x19,0x0C, 0x18,0x0D, 0x17,0x03,   215                                   0x16,0x01, 0x11,0x02, 0x11,0x03, 0x10,0x03, 0x0F,0x0C,   216                                   0x10,0x02, 0x15,0x00, 0x1F,0x01, 0x1A,0x01, 0x18,0x66,   217                                   0x19,0x03, 0x1A,0x01, 0x1B,0x02, 0x1B,0x03, 0x1B,0x03,   218                                   0x1B,0x0C, 0x1A,0x0D, 0x19,0x03, 0x17,0x00, 0x1F,0x01,   219                                   0x1A,0x01, 0x18,0x66, 0x19,0x03, 0x1A,0x01, 0x10,0x02,   220                                   0x10,0x03, 0x10,0x03, 0x1A,0x0C, 0x18,0x0D, 0x17,0x03,   221                                   0x16,0x00, 0x0F,0x01, 0x15,0x02, 0x16,0x02, 0x17,0x70,   222                                   0x18,0x03, 0x17,0x02, 0x15,0x03, 0x15,0x03, 0x16,0x66,   223                                   0x16,0x03, 0x16,0x02, 0x16,0x03, 0x15,0x03, 0x10,0x02,   224                                   0x10,0x01, 0x11,0x01, 0x11,0x66, 0x10,0x03, 0x0F,0x0C,   225                                   0x1A,0x02, 0x19,0x02, 0x16,0x03, 0x16,0x03, 0x18,0x66,   226                                   0x18,0x03, 0x18,0x02, 0x17,0x03, 0x16,0x03, 0x19,0x00,   227                                   0x00,0x00 };   228 //两只蝴蝶                                     229 unsigned char code Music_Two[] ={ 0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,   230                                   0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,   231                                   0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,   232                                   0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x16,0x03,   233                                   0x17,0x01, 0x16,0x03, 0x17,0x03, 0x16,0x03, 0x15,0x01,   234                                   0x10,0x03, 0x15,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,   235                                   0x16,0x03, 0x15,0x03, 0x10,0x03, 0x15,0x03, 0x16,0x01,   236                                   0x17,0x03, 0x16,0x03, 0x17,0x01, 0x16,0x03, 0x17,0x03,   237                                   0x16,0x03, 0x15,0x01, 0x10,0x03, 0x15,0x03, 0x16,0x02,   238                                   0x16,0x0D, 0x17,0x03, 0x16,0x03, 0x15,0x03, 0x10,0x03,   239                                   0x10,0x0E, 0x15,0x04, 0x0F,0x01, 0x17,0x03, 0x19,0x03,   240                                   0x19,0x01, 0x19,0x03, 0x1A,0x03, 0x19,0x03, 0x17,0x01,   241                                   0x16,0x03, 0x16,0x03, 0x16,0x02, 0x16,0x0D, 0x17,0x03,   242                                   0x16,0x03, 0x15,0x03, 0x10,0x03, 0x10,0x0D, 0x15,0x00,   243                                   0x19,0x03, 0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03,   244                                   0x1B,0x03, 0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03,   245                                   0x16,0x0D, 0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03,   246                                   0x1A,0x02, 0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03,   247                                   0x16,0x01, 0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03,   248                                   0x19,0x02, 0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E,   249                                   0x1B,0x04, 0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E,   250                                   0x1B,0x04, 0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03,   251                                   0x17,0x0D, 0x16,0x03, 0x17,0x03, 0x19,0x01, 0x19,0x03,   252                                   0x19,0x03, 0x1A,0x03, 0x1F,0x03, 0x1B,0x03, 0x1B,0x03,   253                                   0x1A,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x03, 0x16,0x03,   254                                   0x17,0x01, 0x17,0x03, 0x17,0x03, 0x19,0x03, 0x1A,0x02,   255                                   0x1A,0x02, 0x10,0x03, 0x17,0x0D, 0x16,0x03, 0x16,0x01,   256                                   0x17,0x03, 0x19,0x03, 0x19,0x03, 0x17,0x03, 0x19,0x03,   257                                   0x1F,0x02, 0x1B,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,   258                                   0x17,0x02, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,   259                                   0x17,0x16, 0x1A,0x03, 0x1A,0x03, 0x1A,0x0E, 0x1B,0x04,   260                                   0x1A,0x03, 0x19,0x03, 0x17,0x03, 0x16,0x03, 0x0F,0x02,   261                                   0x10,0x03, 0x15,0x00, 0x00,0x00 };  262                                   263 unsigned char code Music_birth[]={0x0F,0x03,0x0F,0x03,0x10,0x02,0x0F,0x02,0x15,0x02,0x11,0x01,0x0F,0x03,264                                   0x0F,0x03,0x10,0x02,0x0F,0x02,0x16,0x02,0x15,0x01,0x0F,0x03,0x0F,0x03,265                                   0x19,0x02,0x17,0x02,0x15,0x02,0x11,0x0C,0x10,0x02,0x18,0x03,0x18,0x03,266                                   0x17,0x02,0x15,0x02,0x16,0x02,0x17,0x01,0x0F,0x02,0x0F,0x03,0x10,0x03,267                                   0x0F,0x02,0x15,0x02,0x11,0x01,0x0F,0x03,0x0F,0x03,0x10,0x02,0x0F,0x02,268                                   0x16,0x02,0x15,0x01,0x0F,0x03,0x0F,0x03,0x19,0x02,0x17,0x02,0x15,0x02,269                                   0x11,0x0C,0x10,0x02,0x18,0x03,0x18,0x03,0x17,0x02,0x15,0x02,0x16,0x02,270                                   0x10,0x01,0x00,0x00 };271   272 void main()   273 {   274        275         InitialSound();           276   277            278         while(1)                                   279         {                      280             Play(Music_Girl,0,2,350);   281             Play(Music_Same,0,2,350);   282             Play(Music_Two,0,2,350);  283             Play(Music_birth,0,2,350); 284         }   285 }   

这个代码明显的来自网络。哈哈。原谅我,这个我就不说明了。哎,还是再说一下步骤吧。。(具体我也不是很懂,不同这个真的很通用,所以还是放到笔记上了。。)

一开始就用MUSICENCODE这个将乐谱转换为相应的代码,然后根据音调和音区生成一个新的频率表。所谓的音区就是降调,平调,升调,这个可以根据转换的代码相应位得知。

再计算歌曲的长度,用while就好,用来设置一首歌唱完之后再来一遍还是执行其他动作。

再取出数组数据的奇数位,那个就是表示音长的。然后根据这个计算一个音调唱多久,并将初值赋给定时器。关于定时器的使用,之后会放出。

一个音调唱多久最好的方法就是设置一个基本时长,因为这个例子中,一个四分节拍大概是400ms-500ms,然后有的是1/4拍(100ms),有的2/4拍(200ms),所以就设置一个

50ms的定时器,调用的时候设置一下参数就好了。这样做的好处就是方便。

接着调用函数让它唱歌就好

 

比较一下这两个方法的优缺点,第一种方法转码太复杂,不过声音很好,分辨率高。第二种方法通用!不同的歌,你只要用工具转一下码,然后重新用个数组保存这些值,然后再通过

Play(乐曲名,调号,升降八度,演奏速度)这个函数调用就好了,不过用这种方法实现的效果音质不是很理想。其实最主要的是这种方法对音乐知识不理解也没关系,而第一种方法还是

需要一定的知识来获得正确的音调频率和音长。


[51单片机学习笔记TWO]----蜂鸣器