关于学院网站建设的通知微网站开发商
目录
蜂鸣器播放提示音
蜂鸣器播放音乐(天空之城)
准备工作
主程序
中断函数
上一节讲了蜂鸣器驱动原理和乐理基础知识,这一节开始代码演示!
蜂鸣器播放提示音
先创建工程:蜂鸣器播放提示音
把我们之前模块化的程序文件添加进来

但是这次我们 是要静态显示,所以要把Nixie.c文件中这里删掉

我们要实现的效果是我们按下按键之后,会出现按键提示音。
创建一个Buzzer.c和Buzzer.h文件

具体代码解释请看注释:
Buzzer.c
#include <REGX52.H>
#include <INTRINS.H>//_nop_函数的头文件//蜂鸣器端口:普中A2的板子是P2^5,其他板子的可以试试P1^5
sbit Buzzer=P2^5;//在博主以后的博客中,这个函数就作为蜂鸣器的私有延时函数
void Buzzer_Delay500us()		//@12.000MHz
{unsigned char i;_nop_();//延时一微秒的函数i = 247;while (--i);
}//蜂鸣器的发声时长函数
void Buzzer_Time(unsigned int ms)
{unsigned int i;//蜂鸣器翻转的次数for(i=0;i<ms*2;i++)//一个for循环500us=0.5ms,x*0.5ms*2延时xms{Buzzer=!Buzzer;//翻转蜂鸣器//蜂鸣器的标准提示音是1000HzBuzzer_Delay500us();//每500us=0.5ms翻转一次,那蜂鸣响的周期就是1000Hz}
}
 
Buzzer.h
#ifndef __BUZZER_H__
#define __BUZZER_H__void Buzzer_Time(unsigned int ms);#endif
 
main.c
#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Buzzer.h"unsigned char KeyNum;void main()
{Nixie(1,0);//第一位数码管显示0while(1){KeyNum=Key();//按键按下后将键码赋值给keyNumif(KeyNum)//如果按键按下{Buzzer_Time(100);//蜂鸣器响100msNixie(1,KeyNum);//第1位数码管,显示键码}}
} 
效果请看视频:
蜂鸣器播放提示音
以上就是蜂鸣器播放提示音的代码演示!
蜂鸣器播放音乐(天空之城)
接下来开始演示蜂鸣器播放音乐(天空之城)
开始之前,我们先接着上一篇解释一下这张表格(我们之后都叫它表1)
- 想要的频率在最左边,然后我们不能直接产生频率,我们只有周期,1除以频率就是周期。
 - 我们需要半个周期给它翻转一次,翻转两次才是一个周期,所以翻转频率就是周期除以2,把这个频率取整就是我们的计数值(需要计这么多的数值然后就产生中断)。
 - 那么它怎么计这么长呢?溢出才能产生中断对吧?我们就需要给它提前装好中间值(重装载值),在这个值开始计,计到65536溢出就产生中断了。
 - 为了方便找到对应的音符,我们给这些音符弄个索引,相当于编号。
 
(PS:手机页面请把表格往左滑动就可看到重装载值)
表1:
|   音符  |   频率(Hz)  |   周期(us)  |   周期/2(us)  |   取整  |   重装载值  |   索引  | 
|   1  |   262  |   3816.793893  |   1908.396947  |   1908  |   63628  |   1  | 
|   1#  |   277  |   3610.108303  |   1805.054152  |   1805  |   63731  |   2  | 
|   2  |   294  |   3401.360544  |   1700.680272  |   1701  |   63835  |   3  | 
|   2#  |   311  |   3215.434084  |   1607.717042  |   1608  |   63928  |   4  | 
|   3  |   330  |   3030.30303  |   1515.151515  |   1515  |   64021  |   5  | 
|   4  |   349  |   2865.329513  |   1432.664756  |   1433  |   64103  |   6  | 
|   4#  |   370  |   2702.702703  |   1351.351351  |   1351  |   64185  |   7  | 
|   5  |   392  |   2551.020408  |   1275.510204  |   1276  |   64260  |   8  | 
|   5#  |   415  |   2409.638554  |   1204.819277  |   1205  |   64331  |   9  | 
|   6  |   440  |   2272.727273  |   1136.363636  |   1136  |   64400  |   10  | 
|   6#  |   466  |   2145.922747  |   1072.961373  |   1073  |   64463  |   11  | 
|   7  |   496  |   2016.129032  |   1008.064516  |   1008  |   64528  |   12  | 
|   1  |   523  |   1912.045889  |   956.0229446  |   956  |   64580  |   13  | 
|   1#  |   554  |   1805.054152  |   902.5270758  |   903  |   64633  |   14  | 
|   2  |   587  |   1703.577513  |   851.7887564  |   852  |   64684  |   15  | 
|   2#  |   622  |   1607.717042  |   803.8585209  |   804  |   64732  |   16  | 
|   3  |   659  |   1517.450683  |   758.7253414  |   759  |   64777  |   17  | 
|   4  |   698  |   1432.664756  |   716.3323782  |   716  |   64820  |   18  | 
|   4#  |   740  |   1351.351351  |   675.6756757  |   676  |   64860  |   19  | 
|   5  |   784  |   1275.510204  |   637.755102  |   638  |   64898  |   20  | 
|   5#  |   831  |   1203.369434  |   601.6847172  |   602  |   64934  |   21  | 
|   6  |   880  |   1136.363636  |   568.1818182  |   568  |   64968  |   22  | 
|   6#  |   932  |   1072.961373  |   536.4806867  |   536  |   65000  |   23  | 
|   7  |   988  |   1012.145749  |   506.0728745  |   506  |   65030  |   24  | 
|   1  |   1046  |   956.0229446  |   478.0114723  |   478  |   65058  |   25  | 
|   1#  |   1109  |   901.7132552  |   450.8566276  |   451  |   65085  |   26  | 
|   2  |   1175  |   851.0638298  |   425.5319149  |   426  |   65110  |   27  | 
|   2#  |   1245  |   803.2128514  |   401.6064257  |   402  |   65134  |   28  | 
|   3  |   1318  |   758.7253414  |   379.3626707  |   379  |   65157  |   29  | 
|   4  |   1397  |   715.8196135  |   357.9098067  |   358  |   65178  |   30  | 
|   4#  |   1480  |   675.6756757  |   337.8378378  |   338  |   65198  |   31  | 
|   5  |   1568  |   637.755102  |   318.877551  |   319  |   65217  |   32  | 
|   5#  |   1661  |   602.0469597  |   301.0234798  |   301  |   65235  |   33  | 
|   6  |   1760  |   568.1818182  |   284.0909091  |   284  |   65252  |   34  | 
|   6#  |   1865  |   536.1930295  |   268.0965147  |   268  |   65268  |   35  | 
|   7  |   1976  |   506.0728745  |   253.0364372  |   253  |   65283  |   36  | 
接下来开始新创建一个工程:蜂鸣器播放音乐(天空之城)
把之前写好的定时器模块和Delay函数模块添加进来

接下来就对本节代码的每一个模块进行讲解,PS:讲解重点在代码的注释里。
准备工作
为了方便可以重定义端口号(如果最后整个程序写完之后蜂鸣器没有响,那么请看看自己的板子是不是普中的A2开发板,如是,则要把P1^5改成P2^5):
//蜂鸣器端口定义
sbit Buzzer=P1^5; 
乐理zhonggu,一个四分音符所用时间是500ms,重定义四分音符的时间,把500ms重命名为Speed:
//播放速度,值为四分音符的时长(ms)
#define SPEED	500 
然后我们把表1上的音符与索引重定义:
//音符与索引对应表,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 
其中0在乐谱上表示休止符,表示不弹,这里是没有声音的

然后根据表1上的频率和索引弄成一个数组:
//索引与频率对照表
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,
}; 
接下来我们就把天空之城的乐谱中的每一个音符放进一个数组中
这是《天空之城》的乐谱:

这里我们定义十六分音符为1个时长(125ms),则八分音符就是2个时长,四分音符就是4个时长(500ms),二音符就是8个时长,全音符就是16个时长。时长即下面写的时值。
//乐谱
unsigned char code Music[]={//音符,时值,//1P,	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,//2M6,	4+2,M5,	2,M6, 4,H1,	4,M5,	4+4+4,M3,	4,M4,	4+2,M3,	2,M4,	4,H1,	4,//3M3,	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,//4H1,	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,//5M5,	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,//6H1,	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,//7H2,	4+4+4,M5,	2,M5,	2,H1,	4+2,M7,	2,H1,	4,H3,	4,H3,	4+4+4+4,//8M6,	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,//9H3,	4+4+4,H3,	4,H6,	4+4,H5,	4,H5,	4,H3,	2,H2,	2,H1,	4+4,P,	2,H1,	2,//10H2,	4,H1,	2,H2,	2,H2,	4,H5,	4,H3,	4+4+4,H3,	4,H6,	4+4,H5,	4+4,//11H3,	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	//终止标志,防止数组越界之后乱音,用一个最大值来做一个终止标志,也可以设别的值
};
 
定义两个变量
//FreSelect就是FreqTable[]中的元素的下标,
//MusicSelect就是Music[]中的元素下标unsigned char FreqSelect,MusicSelect; 
主程序
void main()
{Timer0Init();//定时器初始化,1ms后溢出调到中断函数中执行中断//之后每次中断函数执行完之后返回主程序中进入while循环while(1){if(Music[MusicSelect]!=0xFF)	//如果不是停止标志位{FreqSelect=Music[MusicSelect];	//选择音符对应的频率//选择好Music[]里的音符(索引/编号的重定义)之后赋值给FreqTable[]的下标FreqSelect,//然后在中断函数里就把FreqSelect这个下标对应的重装载值赋值给TL0和TH0,//也就是让它产生对应的频率即可发出对应的音符MusicSelect++;//Music[]的下标+1就是该音符的时长的下标Delay(SPEED/4*Music[MusicSelect]);	//选择音符对应的时值//SPEED是500ms//SPEED/4=一个十六分音符的时间125ms//125ms*Music[MusicSelect]=125ms*时值=某个音符的时长MusicSelect++;//Music[]的下标+1就是下一个音符的下标//为了停顿后进入下一次while循环的MusicSelect的初值TR0=0;//关闭定时器Delay(5);	//音符间短暂停顿TR0=1;//开启定时器}else	//如果是停止标志位0xFF{TR0=0;//关闭定时器while(1);//程序就一直停在这里了}}
} 
中断函数
//如果不是休止符,定时器初始化后第一次进来时是FreqTable[0]=0,没有出声,
//第二次进来中断函数才真正开始选(重装载值)
void Timer0_Routine() interrupt 1 //中断函数每1ms进来一次
{if(FreqTable[FreqSelect])	{/*取对应频率值的重装载值到定时器*/TL0 = FreqTable[FreqSelect]%256;		//设置定时初值TH0 = FreqTable[FreqSelect]/256;		//设置定时初值Buzzer=!Buzzer;	//翻转蜂鸣器IO口}
}
 
效果请看视频:
蜂鸣器播放音乐
蜂鸣器播放音乐部分完成!
本节的源码放在评论区了,自取!
如有问题,可评论区留言!
