微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 单片机控制蜂鸣器播放音乐程序遇到问题,求高手帮忙解...

单片机控制蜂鸣器播放音乐程序遇到问题,求高手帮忙解...

时间:10-02 整理:3721RD 点击:
我想用单片机控制蜂鸣器播放一些音乐,用了一个八月桂花遍地开的程序,想把里面的歌曲改掉,用谱曲的软件改了之后,播放的就乱了,没有调子了。求高手解释下怎么改进啊!原程序如下
/************************************************************************  
[文件名]  C51音乐程序(八月桂花)  
[功能]    通过单片机演奏音乐  
/**********************************************************************/   
#include <REG52.H>   
#include <INTRINS.H>   
//本例采用89C52, 晶振为11.0592MHZ   
//关于如何编制音乐代码, 其实十分简单,各位可以看以下代码.   
//频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍;   
//所以拿出谱子, 试探编吧!   
sbit Beep =  P3^7 ;
unsigned char n=0;  //n为节拍常数变量   
unsigned char code music_tab[] ={                                                                 //这里用取谱软件取出生日快乐的歌的代码后,播放时就乱码了。
0x18, 0x30, 0x1C , 0x10, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数, //求解释,望大家能帮帮忙。   
0x20, 0x40, 0x1C , 0x10,   
0x18, 0x10, 0x20 , 0x10,   
0x1C, 0x10, 0x18 , 0x40,   
0x1C, 0x20, 0x20 , 0x20,   
0x1C, 0x20, 0x18 , 0x20,   
0x20, 0x80, 0xFF , 0x20,   
0x30, 0x1C, 0x10 , 0x18,   
0x20, 0x15, 0x20 , 0x1C,   
0x20, 0x20, 0x20 , 0x26,   
0x40, 0x20, 0x20 , 0x2B,   
0x20, 0x26, 0x20 , 0x20,   
0x20, 0x30, 0x80 , 0xFF,   
0x20, 0x20, 0x1C , 0x10,   
0x18, 0x10, 0x20 , 0x20,   
0x26, 0x20, 0x2B , 0x20,   
0x30, 0x20, 0x2B , 0x40,   
0x20, 0x20, 0x1C , 0x10,   
0x18, 0x10, 0x20 , 0x20,   
0x26, 0x20, 0x2B , 0x20,   
0x30, 0x20, 0x2B , 0x40,   
0x20, 0x30, 0x1C , 0x10,   
0x18, 0x20, 0x15 , 0x20,   
0x1C, 0x20, 0x20 , 0x20,   
0x26, 0x40, 0x20 , 0x20,   
0x2B, 0x20, 0x26 , 0x20,   
0x20, 0x20, 0x30 , 0x80,   
0x20, 0x30, 0x1C , 0x10,   
0x20, 0x10, 0x1C , 0x10,   
0x20, 0x20, 0x26 , 0x20,   
0x2B, 0x20, 0x30 , 0x20,   
0x2B, 0x40, 0x20 , 0x15,   
0x1F, 0x05, 0x20 , 0x10,   
0x1C, 0x10, 0x20 , 0x20,   
0x26, 0x20, 0x2B , 0x20,   
0x30, 0x20, 0x2B , 0x40,   
0x20, 0x30, 0x1C , 0x10,   
0x18, 0x20, 0x15 , 0x20,   
0x1C, 0x20, 0x20 , 0x20,   
0x26, 0x40, 0x20 , 0x20,   
0x2B, 0x20, 0x26 , 0x20,   
0x20, 0x20, 0x30 , 0x30,   
0x20, 0x30, 0x1C , 0x10,   
0x18, 0x40, 0x1C , 0x20,   
0x20, 0x20, 0x26 , 0x40,   
0x13, 0x60, 0x18 , 0x20,   
0x15, 0x40, 0x13 , 0x40,   
0x18, 0x80, 0x00   
};   
void int0()  interrupt 1   //采用中断0 控制节拍   
{  TH0=0xd8;   
   TL0=0xef;   
   n--;   
}   
void delay (unsigned char m)   //控制频率延时   
{   
unsigned i=3*m;   
while(--i);   
}   
void delayms(unsigned char a)  //豪秒延时子程序   
{   
  while(--a);                  //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!   
}   
void main()   
{ unsigned char p,m;   //m为频率常数变量   
  unsigned char i=0;   
  //TMOD&=0x0f;   
  TMOD|=0x01;   
  TH0=0xd8;
        TL0=0xef;   
  IE=0x82;     
   while(1)   
    {   
     p=music_tab;   
     if(p==0x00)      
     { i=0, delayms(1000);}     //如果碰到结束符,延时1秒,回到开始再来一遍   
     else if(p==0xff)
     { i=i+1;delayms(100),TR0=0;}  //若碰到休止符,延时100ms,继续取下一音符   
      else      
      {m=music_tab[i++], n=music_tab[i++];}  //取频率常数 和 节拍常数   
         TR0=1;                                             //开定时器1   
         while(n!=0) Beep=~Beep,delay(m);                         //等待节拍完成, 通过P1口输出音频(可多声道哦!)   
       TR0=0;                                             //关定时器1   
    }   
}  

看看顺便学习一下

取谱软件的编解码方式不一样造成的吧

看看顺便学习一下

是这个原因吗?那样怎么改进呢?求指教。我之前想的是音乐有不同的调子和节拍,但是不知道如何设置定时器来改变这些参数。

//格式为: 频率常数, 节拍常数, 频率常数, 节拍常数, //求解释,望大家能帮帮忙。
这一句就是关键,以0x18的频率发音0x30的时间,再以0x1C的频率发音0x10的时间,再以0x20的频率发音0x40的时间,你明白规律了吗?

明白规律       我已经弄清楚了不同的音符对应的频率了(十六进制的那个)但是怎么知道发音的时间呢?怎么算出十六进制的来呢?

我觉得你的程序太复杂了  还有一个是间的c的程序  你查查   我上学时用过

while(n!=0) Beep=~Beep,delay(m);                         //等待节拍完成, 通过P1口输出音频(可多声道哦!)   
这一句是和节拍有关的,只要n不等于0,这个节拍就没完成,而前面的中断函数每中断一次把n减1,可以根据中断算出节拍的实际时间,至于发音时间应该是多长,恐怕这得问一下音乐家了

主函数里面的p变量是什么含义呢?根据p=music_tab;语句,似乎p应该是指针变量,指向music_tab的首地址。那么在下面的if语句中调用的时候,就应该是*p。不知道是否正确,仅供参考。

谢谢你的解答。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top