网站公告列表     本站开通全国范围代收货款业务,详情请点击  [dycxin  2008年5月14日]        
加入收藏
设为首页
联系站长
您现在的位置: EDA加油站 >> MSP430 >> 程序示例 >> 正文
  [推荐]MSP430F1611音乐程序的设置           ★★★ 【字体:
MSP430F1611音乐程序的设置
MSP430F1611音乐程序的设置
作者:佚名    MSP430来源:网络    点击数:    更新时间:2008-11-1    

在网上找了个遍.没找到MSP430的音乐程序.我想应该是MSP430用在这方面还不是大才小用了.于是自己根据AT89C51单片机的蜂鸣器音乐加到移动到430.先看看.AT89C51的用法.再试我的想法.

              一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能象电子琴那样能奏出多种音色的声音。因此单片机奏乐只需弄清楚两个概念即可,也就是“音调”和“节拍”。音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间。

       在音乐中所谓“音调”,其实就是我们常说的“音高”。在音乐中常把中央C上方的A音定为标准音高,其频率f=440Hz当两个声音信号的频率相差一倍时,也即f2=2f1时,则称f2f1高一个倍频程, 音乐中1do)与 2(来)与 ……正好相差一个倍频程,在音乐学中称它相差一个八度音。在一个八度音内,有12个半音。以1i八音区为例, 12个半音是:1—#1、#122—#2、#23344—#4,#455一#5、#566—#6、#677i。这12个音阶的分度基本上是以对数关系来划分的。如果我们只要知道了这十二个音符的音高,也就是其基本音调的频率,我们就可根据倍频程的关系得到其他音符基本音调的频率

       知道了一个音符的频率后,怎样让单片机发出相应频率的声音呢?一般说来,常采用的方法就是通过单片机的定时器定时中断,将单片机上对应蜂鸣器的I/O口来回取反,或者说来回清零,置位,从而让蜂鸣器发出声音,为了让单片机发出不同频率的声音,我们只需将定时器予置不同的定时值就可实现。那么怎样确定一个频率所对应的定时器的定时值呢?以标准音高A为例:

                     A的频率f = 440 Hz,其对应的周期为:

T = 1/ f = 1/440 =2272μs


由上图可知,单片机上对应蜂鸣器的I/O口来回取反的时间应为:

t = T/2 = 2272/2 = 1136μs

这个时间t也就是单片机上定时器应有的中断触发时间。一般情况下,单片机奏乐时,其定时器为工作方式1,它以振荡器的十二分频信号为计数脉冲。设振荡器频率为f0,则定时器的予置初值由下式来确定:

                        

这个时间t也就是单片机上定时器应有的中断触发时间。一般情况下,单片机奏乐时,其定时器为工作方式1,它以振荡器的十二分频信号为计数脉冲。设振荡器频率为f0,则定时器的予置初值由下式来确定:

                            t = 12 *TALL – THL/ f0

              式中TALL = 216 = 65536,THL为定时器待确定的计数初值。因此定时器的高低计数器的初值为:  

                            TH = THL / 256 = ( TALL – t* f0/12) / 256

                            TL = THL % 256 = ( TALL – t* f0/12) %256

t=1136μs代入上面两式(注意:计算时应将时间和频率的单位换算一致),即可求出标准音高A单片机晶振频率f0=12Mhz,定时器在工作方式1下的定时器高低计数器的予置初值为

                            TH440Hz = (65536 1136 * 12/12) /256 = FBH

                            TL440Hz = (65536 1136 * 12/12)%256 = 90H

根据上面的求解方法,我们就可求出其他音调相应的计数器的予置初值。

       音符的节拍我们可以举例来说明。在一张乐谱中,我们经常会看到这样的表达式,如1=C 1=G …… 等等,这里1=C,1=G表示乐谱的曲调,和我们前面所谈的音调有很大的关联, 就是用来表示节拍的。以 为例加以说明,它表示乐谱中以四分音符为节拍,每一小结有三拍。比如:

其中1 2 为一拍,345为一拍,6为一拍共三拍。1 2的时长为四分音符的一半,即为八分音符长,34的时长为八分音符的一半,即为十六分音符长,5的时长为四分音符的一半,即为八分音符长,6的时长为四分音符长。那么一拍到底该唱多长呢?一般说来,如果乐曲没有特殊说明,一拍的时长大约为400—500ms 。我们以一拍的时长为400ms为例,则当以四分音符为节拍时,四分音符的时长就为400ms,八分音符的时长就为200ms,十六分音符的时长就为100ms

可见,在单片机上控制一个音符唱多长可采用循环延时的方法来实现。首先,我们确定一个基本时长的延时程序,比如说以十六分音符的时长为基本延时时间,那么,对于一个音符,如果它为十六分音符,则只需调用一次延时程序,如果它为八分音符,则只需调用二次延时程序,如果它为四分音符,则只需调用四次延时程序,依次类推。

通过上面关于一个音符音调和节拍的确定方法,我们就可以在单片机上实现演奏音乐了。具体的实现方法为:将乐谱中的每个音符的音调及节拍变换成相应的音调参数和节拍参数,将他们做成数据表格,存放在存储器中,通过程序取出一个音符的相关参数,播放该音符,该音符唱完后,接着取出下一个音符的相关参数……,如此直到播放完毕最后一个音符,根据需要也可循环不停地播放整个乐曲。另外,对于乐曲中的休止符,一般将其音调参数设为FFHFFH,其节拍参数与其他音符的节拍参数确定方法一致,乐曲结束用节拍参数为00H来表示。

下面给出部分音符(三个八度音)的频率以及以单片机晶振频率f0=12Mhz,定时器在工作方式1下的定时器高低计数器的予置初值

以上是单片机设置方式. 在设置MSP430时注意设置频率及周期 DCOCLK默认800KHZ,而且频率随外界影响较大,   MCLK通常外接8MHZ 而且MSP430是16bit 执行速度非常快. 周期: 1/800K=1.25us    1/8MHZ=0.125us   这个执行周期是看不同的MCU型号和用什么样的时钟.这里的采用

   MSP430音乐程序设置思路: 将430的指令周期设置为1us这与单片机指令周期一样.只是430是16bit, AT89C51程序在设置"音调"与"节拍"时有两种思路.1>定时器T0用于音调. 定时器T1用于节拍. 反过来均可 2>定时器T0 即用于单调产生也用于节拍.或T1也能实现此功能.

在实现音调定时功能是动态修改定时器的值. 先将定时器中断的启动关闭.再修改TH0与TL0或者TH1与TL1的值再开启中断. 我使用430的方法和AT89C51类似.将TACTL 或TBCTL暂停.重设置TBCCR0的值,默认的指令周期就是1800 kHz=125μs。要得到lμs的指令周期需要调整DCO频率,即MCLK=1 MHz,只需进行如下设置:BCSCTLl=XT20FF+RSEL2

    //关闭XT2振荡器,设定DCO频率为1 MHz

    DCOCTL=DCO2

    //使得单指令周期为lμs

程序如下:

#define Uint unsigned int
#define Uchar unsigned char
unsigned int j;            //数组变量;
long int MySound;      //对两声音数组的值,赋值
//void DelayMS(Uint ms);
void Init_SystemClock(void);
void Init_Port(void);
void Init_TimerB(void);
__interrupt void TimerB_ISR(void);

void DelayMs(Uchar ms)
{
while(ms--)
{
   for(Uint i=0;i<48000;i++);
};
}

void main(void)
{ Uchar MySoun;
WDTCTL=WDTPW+WDTHOLD;
Init_SystemClock();
Init_Port();

       MySound |=song[j];
       MySound <<4;
       MySound |=song[j+1];

Init_TimerB();
led = 0x01;
_EINT();                  //进中断
// Uint tt;
// tt=sizeof(song);
while(1)
{
    j=0;
     while(j<75)
     {
       MySoun =song[j];
       MySound = (int)MySoun;
       MySound <<4;
       MySoun =song[j+1];
       MySound |= (int)MySoun;
      
       TBCCTL0 |=CCIE;
      if((song[j]==0xff)&&(song[j+1]==0xff)) TBCCTL0 &=~CCIE;   //禁止中断
        DelayMs(song[j+2]);
        j=j+3;
     }
}
}

void Init_Port(void)
{
P4DIR = 0XFF;
P5DIR |=BIT7;
return;
}

void Init_SystemClock(void)
{
unsigned char i;
BCSCTL1=0X00;
//BCSCTL2=0x88;                       //SMCLK   8MHZ   MCLK   8MHZ  

BCSCTL1|=XT2OFF+RSEL2;              //根据MSP430 P119 120图
DCOCTL=DCO2;
do
{
    IFG1&=~OFIFG;
    for(i=0;i<255;i++);
}while((IFG1&OFIFG)!=0);

P5DIR=BIT4+BIT5+BIT6;
P5SEL=BIT4+BIT5+BIT6;               //P5.4 P5.5 P5.6 三端分别输出ACLK SMCLK MCLK 信号
//BCSCTL2|=DIVS_3 + DIVM_3;
//BCSCTL2|=DIVS_3 + DIVM_3;           //SMCLK 是 1MHZ   MCLK 是 8MHZ/8
                                      //TA只用ACLK 与MCLK 因此将MCLK8分频.

return;
}

void Init_TimerB(void)
{
TBCTL=TBSSEL0+TBCLR;
TBCCTL0|=CCIE;
//TBCCR0=32768;
//TBCCR0=123;
TBCCR0=MySound;
TBCTL|=MC0;
return;
}

#pragma vector=TIMERB0_VECTOR
__interrupt void TIMERB_ISR(void)
{
led=(led==0x80)?0x01:(led<<1);
P4OUT=led;
TBCCR0=MySound;
P5OUT ^=BIT7;           //取反
//SPK_High;
//Delay(100);
//SPK_Low;
//Delay(100);
}

void Delay(Uchar ms)
{
while(ms--)
{
for( Uint i=0;i<254;i++);
};
}     欢迎交流! ^_^

MSP430录入:dycxin    责任编辑:dycxin 
  • 上一篇MSP430:

  • 下一篇MSP430: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    太阳能热水器上水控制器V10.…
    MSP430F413做的DS18B20温度计
    MSP430笔记(一)
    使用MSP430系列入门
    UCOS移植到MSP430过程与心得…
    UCOS移植到MSP430过程与心得…
    UCOS移植到MSP430过程与心得…
    UCOS移植到MSP430过程与心得…
    UCOS移植到MSP430过程与心得…
    UCOS移植到MSP430过程与心得…
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    EDA加油站|我要EDA网|山东电子网--东营市荣燕商贸有限公司版权所有! 站长:阿荣
    联系电话:0546-7870320,13371507828 电邮:51edacn@163.com
    山东东营西城济南路百祥电脑商城B302室 邮编:257000 鲁ICP备07018763号  鲁ICP备07000091号 鲁ICP备05003434号
    公司帐号:1615011209000037682 户名:东营市荣燕商贸有限公司 开户行:工行西城支行石油大学分理处