51单片机 蜂鸣器播放音乐

main.c中

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"

//蜂鸣器端口定义
sbit Buzzer=P1^5;

//播放速度,值为四分音符的时长(ms)
#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,
    63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
    64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
    65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
};

//乐谱 code,rom可存8k数据,只读不能在主函数修改
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+4,
    P,    2,
    H1,    2,
    H1,    2,
    H1,    2,
    
    M7,    4+2,
    M4_,2,
    M4_,4,
    M7,    4,
    
    M7,    8,
    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,
    H3,    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,
    P,    4,
    
    0xFF    //终止标志
};

unsigned char FreqSelect,MusicSelect;

void main()
{
    Timer0_Init();
    while(1)
    {
        if(Music[MusicSelect]!=0xFF)    //如果不是停止标志位
        {
            FreqSelect=Music[MusicSelect];    //选择音符对应的频率
            MusicSelect++;
            Delay(SPEED/4*Music[MusicSelect]);    //选择音符对应的时值
            MusicSelect++;
            TR0=0;
            Delay(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口
    }
}
delay.c中

void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

delay.h中

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

Timer0.c

#include <REGX52.H>

void Timer0_Init()
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x18;        //设置定时初始值
    TH0 = 0xFC;        //设置定时初始值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;
    EA=1;
    PT0=0;
}

/*
定时器中断函数模板,使用时复制到main.c中
void Timer0_Routine() interrupt  1

   static unsigned int T0Count;
   TL0 = 0x18;        //设置定时初始值
   TH0 = 0xFC;
   T0Count++;
   if(T0Count>=1000)
   {
     T0Count=0;
    
   }
  
  
}
*/

Timer0.h中

#ifndef __TIMER0_H__
#define    __TIMER0_H__

void Timer0_Init(void);


#endif

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这是一个比较简单的51单片机蜂鸣器按键播放音乐的程序。 首先,需要定义一些常量和变量: ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit beep = P1^5; // 蜂鸣器控制引脚 sbit key1 = P3^2; // 按键1 sbit key2 = P3^3; // 按键2 uchar code music[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; // 音乐数据 uchar music_index = 0; // 当前播放音乐的索引 ``` 其中,sbit表示单片机某个引脚的控制,code表示将音乐数据存储在程序存储空间中,而不是在RAM中(节省RAM空间)。 然后,需要初始化单片机的一些参数: ```c void init() { TMOD = 0x01; // 定时器0工作在模式1 TH0 = 0x4C; // 定时器0的高八位 TL0 = 0x00; // 定时器0的低八位 TR0 = 1; // 启动定时器0 ET0 = 1; // 开启定时器0中断 EA = 1; // 开启总中断 } ``` 这里使用定时器0来控制蜂鸣器发声。定时器0的工作模式为模式1,即16位定时器,每次计数到65536时,会产生中断。TH0和TL0分别是定时器0的高八位和低八位,这里设置定时器0的总计数为20000,即蜂鸣器每秒发声20000次。TR0表示启动定时器0,ET0表示开启定时器0中断,EA表示开启总中断。 接着,需要编写定时器0中断处理函数: ```c void timer0() interrupt 1 { TH0 = 0x4C; // 重新设置定时器0的高八位 TL0 = 0x00; // 重新设置定时器0的低八位 if (music[music_index] == 0x00) { // 如果音乐播放完毕 music_index = 0; // 重新开始播放 } if (music[music_index] == 0x01) { // 如果当前音符为1,则蜂鸣器发声 beep = ~beep; // 反转蜂鸣器控制引脚 } music_index++; // 播放下一个音符 } ``` 在定时器0中断处理函数中,首先重新设置定时器0的高八位和低八位,然后判断当前音乐是否播放完毕,如果是,则重新开始播放;如果当前音符为1,则蜂鸣器发声,即将蜂鸣器控制引脚反转;最后,播放下一个音符。 最后,需要编写主函数中的按键扫描代码: ```c void main() { init(); // 初始化 while (1) { if (key1 == 0) { // 如果按键1按下 music_index = 0; // 重新开始播放音乐 } if (key2 == 0) { // 如果按键2按下 music_index = 0; // 重新开始播放音乐 music[0] = 0x01; // 设置第一个音符为1(即发声) } else { music[0] = 0x00; // 设置第一个音符为0(即静音) } } } ``` 在主函数中,使用while(1)循环不断扫描按键状态。如果按键1按下,则重新开始播放音乐;如果按键2按下,则重新开始播放音乐,并将第一个音符设置为1,即蜂鸣器开始发声,直到按键2松开。如果按键2没有按下,则第一个音符为0,即蜂鸣器静音。 完整代码如下:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值