蜂鸣器播放音乐+普中51单片机+江科大自化协

1 现象

  利用蜂鸣器实现音乐播放功能,播放《天空之城》。

2 原理

(1)天空之城的乐谱

 

 3 参考程序

3.1 主程序

#include <REGX52.H>
#include "delayms.h"
#include "timer0.h"

//蜂鸣器端口定义
sbit buzzer = P2^5;

//播放速度,值为四分音符的时长
#define SPEED 500

//音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P    0
#define L1    1
#define L1_    2
#define L2    3
#define L2_    4
#define L3    5
#define L4    6
#define L4_    7
#define L5    8
#define L5_    9
#define L6    10
#define L6_    11
#define L7    12
#define M1    13
#define M1_    14
#define M2    15
#define M2_    16
#define M3    17
#define M4    18
#define M4_    19
#define M5    20
#define M5_    21
#define M6    22
#define M6_    23
#define M7    24
#define H1    25
#define H1_    26
#define H2    27
#define H2_    28
#define H3    29
#define H4    30
#define H4_    31
#define H5    32
#define H5_    33
#define H6    34
#define H6_    35
#define H7    36

//索引与频率对照表
unsigned int FreqTable[]={
    0,
    63472,63584,63697,63797,63897,63987,64074,64156,64233,64307,64376,64441,
    64502,64560,64615,64667,64715,64761,64805,64846,64885,64921,64956,64989,
    65020,65048,65076,65102,65126,65149,65171,65191,65210,65229,65246,65262
};

//乐谱,天空之城,频率,音长
unsigned char code Music[]={
    //第1行
    P,    4,    P,    4,    P,    4,    M6,    2,    M7,    2,
    H1,    4+2,M7,    2,    H1,    4,    H3,    4,
    M7,    4+4+4,        M3,    2,    M3,    2,
    //第2行
    M6,    4+2,M5,    2,    M6,    4,    H1,    4,
    M5,    4+4+4,        M3,    4,
    M4,    4+2,M3,    2,    M4,    4,     H1,    4,
    //第3行
    M3,    4+2,P,    2,    H1,    2,    H1,    2,    H1,    2,
    M7,    4+2,M4_,2,    M4_,4,    M7,    4,
    M7,    4+4,P,    4,    M6,    2,    M7,    2,
    //第4行
    H1, 4+2,M7,    2,    H1,    4,    H3,    4,
    M7,    4+4+4,    M3,    2,    M3,    2,
    M6,    4+2,    M5,    2,    M6,    4, H1,    4,
    //第5行
    M5,    4+4+4,    M2,    2,    M3,    2,
    M4,    4,    H1,    2,    M7,    2+2,    H1,    2+4,
    H2,    2,    H2,    2,    H3,    2,    H1,    2+4+4,
    //第6行
    H1,    2,    M7,    2,    M6,    2,    M6,    2,    M7,    4,    M5_,4,
    M6,    4+4+4,    H1,    2,    H2,    2,
    H3,    4+2,H2,    2,    H3,    4,    H5,    4,
    //第7行
    H2,    4+4+4,    M5,    2,    M5,    2,
    H1,    4+2,    M7,    2,    H1,    4,    H3,    4,
    H3,    4+4+4+4,
    //第8行
    M6,    2,    M7,    2, H1,    4,    M7,    4,    H2,    2,    H2,    2,
    H1,    4+2,M5,    2+4+4,
    H4,    4,    H3,    4,    H2,    4,    H1,    4,
    //第9行
    H3,    4+4+4,    H3,    4,
    H6,    4+4,    H5,    4,    H5,    4,
    H3,    2,    H2,    2,    H1,    4+4,    P,    2,    H1,    2,
    //第10行
    H2,    4,    H1,    2,    H2,    2,    H2,    4,    H5,    4,
    H3,    4+4+4,    H3,    4,
    H6,    4+4,    H5,    4+4,
    //第11行
    H3,    2,    H2,    2,    H1,    4+4,    P,    2,    H1,    2,
    H2,    4,    H1,    2,    H2,    2+4,    M7,    4,
    M6,    4+4+4,    M6,    2,    M7,    2,
    
    0xFF    //终止符号
};

unsigned char FreqSelect,MusicSelect;

void main()
{
    timer0_init();
    while(1)
    {
        if(Music[MusicSelect]!=0xFF)    //如果不是停止标志位
        {
            FreqSelect = Music[MusicSelect];    //选择音符对应的频率
            MusicSelect++;
            delayms(SPEED/4*Music[MusicSelect]);    //选择音符对应的时值
            MusicSelect++;
            TR0 = 0;    
            delayms(5);        //音符间短暂停顿
            TR0 = 1;
        }
        else            //如果是停止标志位,停止播放
        {
            TR0 = 0;
            while(1);
        }
    }
}

void timer0_routine() interrupt 1
{
    if(FreqTable[FreqSelect])    //如果不是休止符
    {
        /*取对应频率值的重装载值到定时器*/
        TL0 = FreqTable[FreqSelect]%256;        //设置定时初值
        TH0 = FreqTable[FreqSelect]/256;        //设置定时初值
        buzzer=!buzzer;    //翻转蜂鸣器IO口
    }
}

3.2 延时函数

#ifndef _delayms_h_
#define _delayms_h_

    delayms(unsigned int xms);
    
#endif
#include <intrins.h>

void delayms(unsigned int xms)        //@11.0592MHz
{
    unsigned char i, j;

    while(xms--)
    {
        _nop_();
        i = 2;
        j = 199;
        do
        {
            while (--j);
        } while (--i);    
    }
}

3.3 定时器函数

#ifndef _timer0_h_
#define _timer0_h_

    void timer0_init(void);
    
#endif
#include <REGX52.H>

/**
  * @brief  定时器0初始化,1毫秒@11.0592MHz
  * @param  无
  * @retval 无
  */
void timer0_init(void)        //1毫秒@11.0592MHz
{
    TMOD &= 0xF0;    //设置定时器模式,1111_0000,&,高四位保留,低四位清零
    TMOD |= 0x01;    //设置定时器模式,0000_0001,|,高四位保留,设置模式为T0
    TL0 = 0x66;        //设置定时初始值,1ms,@11.0592MHz
    TH0 = 0xFC;        //设置定时初始值,1ms,@11.0592MHz
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;            //打开定时器T0中断开关
    EA=1;            //打开中断系统总开关
    PT0=0;            //设置T0中断优先级,低
}

 

posted @ 2023-01-01 20:27  豌豆茶  阅读(2078)  评论(0编辑  收藏  举报