51单片机演奏音乐--源代码

搬一篇文章过来,2009年本人写在网易博客上的,现在网页博客已经关了,先挪过来,避免以后不在了。

关于程序的补充说明:

1、两个定时器的作用,及中断优先级的问题。
(1)定时器0——是一直输出方波,直到音乐结束;优先级最高;
(2)定时器1——控制输出方波的时间。当输出一个音符的时间到达规定长度时,改变定时器0的计数值,也就是改变方波频率,输出下一个音符;
2、系统的时钟频率
   注意下系统的时钟频率;

 

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

文件名:  MusicPlay.c
描  述:
         单片机演奏音乐;

程序结构描述:
main()函数在初始化后即进入while(1);功能主要在两个中断中完成;
定时器0中断主要输出一定频率的方波,初始值在于FreqTab中获取;
定时器1中断完成音长的控制,在完成特定音符的音长后读取下一个
音符,并且更新定时器0的初始设置值;

补充音乐知识:
音乐主要由音频和音长;
换个角度,
要输出一首音乐即用一个IO口输出特定时间长度和频率的方波

|<-------  音长1(节拍)  --------->| <----  音长2(节拍)------>| ...
      __     __     __      __      __       ___        ___       ___
|__|    |__|    |__|    |__|    |__|    |___|      |___|      |___|      |___

|       音符1(频率1)              |     音符2(频率2)   |  ...
Email:xiesx1985@126.com
by xiesx,2008.12.26
**************************************************************/

 

#include <reg51.h>

unsigned char volatile FlagBeat;   // 基本节拍单位计数变量
unsigned int volatile FreqTemp;
unsigned char volatile music_temp; //暂时存放从MusicTable数组中读出的变量
unsigned char volatile beat;   //
unsigned char volatile freq;   //简谱码对应T值数组的下标
unsigned char volatile   *pmusic;

sbit Pin_Buzzer=P1^0;

unsigned int code FreqTab[]={ //简谱对应的简谱码、T值
                              65535,
         64260,64400,64524,64580,64684,
         64777,64820,64898,64968,65030,
         65058,65110,65157,65178,65217
                            };

unsigned char code MusicTable[]={//音符节拍码
                                  0x82,0x01,0x81,0x94,0x84,
          0xb4,0xa4,0x04,
          0x82,0x01,0x81,0x94,0x84,
          0xc4,0xb4,0x04,
         
          0x82,0x01,0x81,0xf4,0xd4,
          0xb4,0xa4,0x94,
          0xe2,0x01,0xe1,0xd4,0xb4,
          0xc4,0xb4,0x04,
        
          0x82,0x01,0x81,0x94,0x84,
          0xb4,0xa4,0x04,
          0x82,0x01,0x81,0x94,0x84,
          0xc4,0xb4,0x04,

          0x82,0x01,0x81,0xf4,0xd4,
          0xb4,0xa4,0x94,
          0xe2,0x01,0xe1,0xd4,0xb4,
          0xc4,0xb4,0x04,

          0x00

          };

//中断优先级最高,产生FreqTab表中对应的频率
void timer0() interrupt 1 using 0
{
 TR0=0;
 TL0= FreqTemp;
    TH0= FreqTemp>>8;
 TR0=1;
    Pin_Buzzer=~Pin_Buzzer;
}

//用于控制音长的定时中断, 每1/4拍变量FlagBeat加1
//47ms中断一次
void timer1() interrupt 3 using 1
{
 FlagBeat++;
 TR1=0;
 TL1=0x68;
 TH1=0x48;
 TR1=1;
 //
   if(*pmusic==0x00)pmusic=MusicTable;
     {
    if(FlagBeat==beat)
    {
     FlagBeat=0;
    music_temp=*pmusic;
     beat= music_temp&0x0F; //取得节拍数
      beat=beat*4;
     freq =music_temp>>4; //取得音符编码
     pmusic++;
   
     if(freq==0)TR0=0;
     else
     {
          TR0=0;
    FreqTemp=FreqTab[freq];
          TL0= FreqTemp;
          TH0= FreqTemp>>8;
          TR0=1;
     }
    }
       }
 
}
void main()
{
 
    pmusic=MusicTable;
 beat=1;
    FlagBeat=0;
 TMOD=0x11;//定时器0,1都工作16位计数方式 
 ET0=1;   //允许定时器0溢出中断;
 ET1=1;   //允许定时器1溢出中断
 EA=1;
 TL1=0xF0;
    TH1=0xFF;
    TR1=1;

 while(1)
 {

 }
 
}

 

  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HappyShengxiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值