Advertisement

51单片机实验-蜂鸣器播放音乐

阅读量:

该实验通过单片机51实现蜂鸣器播放茉莉花乐曲,利用三极管驱动蜂鸣器,并通过中断函数控制声音。代码中定义了中音、高音和低音的频率数组,以及定时器重载值表,用于计算不同音符的发声时间。中断服务函数负责控制蜂鸣器的发声与停止,实现音乐节拍的精准播放。

51单片机实验-蜂鸣器播放音乐

编程实现利用单片机使蜂鸣器播放茉莉花的乐曲。在单片机开发中,通过三极管驱动蜂鸣器,根据乐谱设置节拍的发声时长。中断函数被用来控制蜂鸣器的发声。

复制代码
    #include<reg51.h> 
    sbit Buzz = P1^6; //声明绑定蜂鸣器,接线时只需将此IO口与蜂鸣器(扬声器)信号输入端相连即可
    unsigned int code NoteFrequ[]={   
    	523,587,659,698,784,880,988,    //中音对应的1-7  
    	1047,1175,1319,1397,1568,1760,1976,	//高音对应的1-7
    	262,294,330,349,392,440,494};  //低音对应的1-7
    
    unsigned int code NoteReload[]={ //中音1-7和高音1-7对应的定时器重载值
    	65536 - (11059200/12) /(523*2),//中音1-7  
    	65536 - (11059200/12) /(587*2),  
    	65536 - (11059200/12) /(659*2),
    	65536 - (11059200/12) /(698*2),
    	65536 - (11059200/12) /(784*2),  
    	65536 - (11059200/12) /(880*2),
    	65536 - (11059200/12) /(988*2),
    	65536 - (11059200/12) /(1047*2),//高音1-7  
    	65536 - (11059200/12) /(1175*2),  
    	65536 - (11059200/12) /(1319*2),  
    	65536 - (11059200/12) /(1397*2),
    	65536 - (11059200/12) /(1568*2),
    	65536 - (11059200/12) /(1760*2),
    	65536 - (11059200/12) /(1976*2),
    	65536 - (11059200/12) /(262*2), //低音1-7
    	65536 - (11059200/12) /(294*2),
    	65536 - (11059200/12) /(330*2),
    	65536 - (11059200/12) /(349*2),
    	65536 - (11059200/12) /(392*2),
    	65536 - (11059200/12) /(440*2),
    	65536 - (11059200/12) /(494*2)};
    
    bit enable = 1; //发声使能表标识
    bit tmrflay = 0; //定时器中中断完成标识
    
    unsigned char T0RH = 0xff; //T0重载值高字节
    unsigned char T0RL = 0x00; //T0重载值低字节
    void PlayTwoTiger(); void main()
    {   
    	unsigned int i;
    EA = 1;
    	TMOD =0x01;  //模式1	
    	TH0 = T0RH;
    	TL0 = T0RL;  
    	ET0 = 1;  //使能T0中断
    TR0 = 1;  //启动
    while(1)
    	{  
    		PlayTwoTiger();
    		for(i=0;i<40000;i++); 
    }
    }
    /**音乐函数**/
    void PlayTwoTiger()
    {
    	unsigned char beat;    //节拍索引
    	unsigned char note;    //节拍对应音符
    	unsigned int time=0;   //节拍计时
    	unsigned int beattime=0;  //总时间计时
    	unsigned int soundtime=0; //没拍发声计时
    	unsigned char code PlayTwoTigerNote[]={ //音符表
    		3,3,5,6,8,8,6,5,5,6,5,
    		3,3,5,6,8,8,6,5,5,6,5,
    		5,5,5,3,5,6,6,5,
    		3,2,3,5,3,2,1,1,2,1,
    		3,2,1,3,2,3,5,6,8,5,
    		2,3,5,2,3,1,20,19,
    		20,1,2,3,
    		1,2,1,20,19
    		};  
    	unsigned char code PlayTwoBeat[]={  //节拍表,4表示一拍,1表示1/4拍,8表示两拍
    		4,2,2,2,2,2,2,4,2,2,8,
    		4,2,2,2,2,2,2,4,2,2,8,
    		4,4,4,2,2,4,4,8,
    		4,2,2,4,2,2,4,2,2,8,
    		2,2,2,2,6,2,4,2,2,8,
    		4,2,2,2,2,2,2,8,
    		4,4,6,2,
    		2,2,2,2,16
    		};   
    	for(beat=0; beat<sizeof(PlayTwoTigerNote);) //节拍索引循环变量
    	{		   
    		while(!tmrflay);   //每次定时器中断完成 节拍处理 
    		tmrflay = 0;       
    		if(time == 0)      //节拍播放完成重启
    		{
    			note = PlayTwoTigerNote[beat]-1;
    			T0RH = NoteReload[note]>>8;
    			T0RL = NoteReload[note];     //计算总时间,右移2位等于除4,移位代替除法加快速度
    			beattime = (PlayTwoBeat[beat]*NoteFrequ[note])>>2;   //计算发声时间,为总时间的0.75s
    			soundtime =beattime - (beattime>>2);  
    			enable = 1;  //开始发声  
    			time++;   
    		}
    		else    //节拍播放未结束,则继续处理
    		{
    			if(time >= beattime) //当前时间清零  
    			{
    				time = 0;     //准备重新启动
    				beat++;   
    			}
    			else      //累加时间
    			{
    				time++;   
    				if(time == soundtime)    //发声时间到达;关闭蜂鸣器
    				{
    					enable =0;      //用以区分连续两个节拍  
    				}
    			}  
    		}
    	}
    }
    
    void InterRupt() interrupt 1   //中断服务
    {
    	TH0 =T0RH;
    	TL0 =T0RL;
    	tmrflay = 1;
    	if(enable)
    	{  
    		Buzz=~Buzz;
    	}
    	else
    	{   
    		Buzz=1;
    	}
    }

若有问题,评论留言~

全部评论 (0)

还没有任何评论哟~