搜索
bottom↓
回复: 10

51单片机音乐C程序怎么解读????

[复制链接]

出0入0汤圆

发表于 2009-10-22 20:41:43 | 显示全部楼层 |阅读模式
#include <reg52.h>
unsigned char Count;
sbit _Speak =P2^3 ;                        //讯响器控制脚 

unsigned char code SONG[] ={      //祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,
                                  //路边的野华不要采
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 Time0_Init()
{
        TMOD = 0x01;
        IE          = 0x82;
        TH0  = 0xD8;
        TL0  = 0xEF;                //12MZ晶振,10ms
}

void Time0_Int() interrupt 1
{
        TH0 = 0xD8;
        TL0 = 0xEF;
        Count++;                        //长度加1
}

/*-------------------------------------------------
功能:1MS延时子程序
-------------------------------------------------*/
void Delay_xMs(unsigned int x)
{
    unsigned int i,j;
    for( i =0;i < x;i++ )
    {
        for( j =0;j<3;j++ );
    }
}

/*-------------------------------------------------
功能:歌曲播放子程序i为播放哪一段曲目
-------------------------------------------------*/
void Play_Song(unsigned char i)
{
        unsigned char Temp1,Temp2;
        unsigned int Addr;
        Count = 0;                                                //中断计数器清0
        Addr = i * 217;
        while(1)
        {
                Temp1 = SONG[Addr++];
            if ( Temp1 == 0xFF )          //休止符
            {
                    TR0 = 0;
                    Delay_xMs(100);
            }
            else if ( Temp1 == 0x00 )          //歌曲结束符
            {
                        Addr++;
                         i++;
                        if(i==2)
                        {
                                i=0;
                            return;
                        }
            }
            else
            {
                    Temp2 = SONG[Addr++];
                    TR0 = 1;
                          while(1)
                          {
                            _Speak = ~_Speak;
                            Delay_xMs(Temp1);
                            if ( Temp2 == Count )
                            {
                                    Count = 0;
                                    break;
                            }
                         }
            }
        }
}
/*-------------------------------------------------
功能:主程序
-------------------------------------------------*/
void main()
{
        Time0_Init();                        //定时器0中断初始化
        while(1)
        {
                Play_Song(0);
        }
}

程序看似简单,但是就是不明白,数组里的一个字节什么意思??
else
            {
                    Temp2 = SONG[Addr++];
                    TR0 = 1;
                          while(1)
                          {
                            _Speak = ~_Speak;
                            Delay_xMs(Temp1);
                            if ( Temp2 == Count )
                            {
                                    Count = 0;
                                    break;
                            }
                         }
            }
        }
这里也不明白???

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2009-10-22 21:02:19 | 显示全部楼层
应该是代表时间长短吧

出0入0汤圆

发表于 2009-10-22 21:16:24 | 显示全部楼层
请问一下楼主,你的这个程序确定没有问题吗?

出0入0汤圆

 楼主| 发表于 2009-10-22 22:04:51 | 显示全部楼层
我从网上找的,看这个结构比较简单,我试过,没问题。。

出0入0汤圆

发表于 2010-7-3 11:08:05 | 显示全部楼层
这程序貌似有问题吧,定时器中断里TH0,TL0为固定值?

出0入0汤圆

发表于 2010-12-7 21:28:56 | 显示全部楼层
#include <reg52.h>
unsigned char Count;
sbit _Speak =P3^7 ;                        //讯响器控制脚 
unsigned char code SONG[] ={      //祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,0x20,0x30,0x20,
0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,
0x20,0x80,0x2b,0x20,0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,
0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,
0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,0x10,
0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,0x2b,0x10,0x2b,0x80,
0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,
0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,
0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,
//路边的野华不要采
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,

};
/*******************************************************************************
** 函数:Time0_Init()
** 描述:定时器0赋初值,晶振为12M,定时10ms
*******************************************************************************/
void Time0_Init()     
{
        TMOD = 0x01;   //定义为16位计数器
        IE   = 0x82;   //0x82 转化为二进制时为1000 0010 ,意思为开总中断,开定时器0中断.
        TH0  = 0xD8;    //高四位赋初值   也可写为TH0=(65536-10000)/256
        TL0  = 0xEF;    // 低四位赋初值  也可写为TL0=(65536-10000)%256      
}
/*******************************************************************************
** 函数:Time0_Int() interrupt 1
** 描述:定时器0中断
*******************************************************************************/
void Time0_Int() interrupt 1   
{
        TH0=0xD8;     //重赋初值
        TL0=0xEF;    //重赋初值
        Count++;         //长度加1
}
/*******************************************************************************
** 函数:Delay_xMs(unsigned int x)
** 描述:  50us
*******************************************************************************/
void Delay_xMs(unsigned int x)
{
        unsigned int i,j;
        for(i=0;i<x;i++)
        {
                for(j=0;j<3;j++);
        }
}
/*******************************************************************************
** 函数:Play_Song
** 描述:歌曲播放子程序i为播放哪一段曲目
*******************************************************************************/
void Play_Song(unsigned char i)
{
        unsigned char Temp1,Temp2;   //Temp1(频率)调用数组内的单数,Temp2(拍子)调用数组里的偶数,
        unsigned int Addr;
        Count=0;      //中断计数器清0   过10ms自加一次.
        Addr=i*217;   //如果i为0,计算从0开始,如果i为1,计算从217开始,也就是第二首歌的起始地址.
        while(1)
        {
                Temp1=SONG[Addr++];      
                if(Temp1==0xFF)          //休止符
                {
                        TR0=0;   //关闭TO.
                        Delay_xMs(100);
                }
                else if (Temp1==0x00)          //歌曲结束符
                {
                        Addr++;
                        i++;
                        if(i==2)
                        {
                                i=0;
                                return;    //返回
                        }
                }
                else
                {
                        Temp2=SONG[Addr++];
                        TR0=1;   //开定时器T0
                        while(1)
                        {
                                _Speak = ~_Speak;
                                Delay_xMs(Temp1);
                                if (Temp2== Count)
                                {
                                        Count = 0;
                                        break;    //跳出while(1)循环
                                }
                        }
                }
        }
}
/*******************************************************************************
** 函数:main()
** 描述:
*******************************************************************************/
void main()
{
        Time0_Init();                        //定时器0中断初始化
        while(1)
        {
                Play_Song(0);
        }
}  






这是我对你的程序的一些注释,希望能对你有所帮助.  
可能也有很多不足之处,希望大家多多指正.

出0入0汤圆

发表于 2010-12-8 00:36:55 | 显示全部楼层
else  
{  
Temp2=SONG[Addr++];  
TR0=1;   //开定时器T0
while(1)  
{  
_Speak = ~_Speak;  
Delay_xMs(Temp1);  
if (Temp2== Count)  
{  
Count = 0;  
break;    //跳出while(1)循环
}  
}  
}  
这一段注释的不是太清楚,麻烦楼上再解释下好吗?

出0入0汤圆

发表于 2010-12-8 00:41:59 | 显示全部楼层
有点理解了,temp1代表频率,temp2代表这种频率声音持续的时间。

出0入0汤圆

发表于 2010-12-8 00:44:07 | 显示全部楼层
注意这段音乐程序的实现是:频率(声音高低),节拍(是这个频率的持续时间)。

出0入0汤圆

发表于 2011-2-22 23:35:20 | 显示全部楼层

出0入0汤圆

发表于 2012-12-4 13:13:59 | 显示全部楼层
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 20:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表