单片机蜂鸣器音乐演奏程序的解释
单片机蜂鸣器编程技巧

单片机蜂鸣器编程技巧1.音乐节奏控制:在编写程序时,可以使用定时器来控制蜂鸣器的音符持续时间。
通过调整定时器的参数值,可以实现不同音长的音符,从而控制节奏感。
2.音符频率控制:不同音符具有不同的频率,可以根据乐谱中各个音符的频率,将其对应的频率值存储在一个数组中。
通过控制蜂鸣器输出的频率,可以实现不同音高的音符。
3.延时函数:在单片机编程中,经常需要使用延时函数来控制时间间隔。
在输出音乐时,可以通过延时函数控制每个音符的持续时间。
通过调整延时函数的参数值,可以实现不同音符间的时间间隔,从而实现更好听的音乐效果。
4.音乐合奏:在编写程序时,可以将不同乐器的音符同时输出到不同的蜂鸣器上,从而实现多个乐器的合奏效果。
通过合理地组合不同乐器的频率和节奏,可以编写出更丰富的音乐作品。
5.音乐循环播放:通过编写循环结构,可以实现音乐循环播放的效果。
通过精确地确定循环次数,可以实现指定音乐节拍的循环播放效果。
6.音乐速度调节:通过调整延时函数的参数值,可以控制音乐的播放速度。
加快延时时间可以使音乐播放加速,减慢延时时间可以使音乐放慢。
7.音乐音量控制:通过控制蜂鸣器输出的PWM信号的占空比,可以实现音乐的音量控制。
调整PWM信号占空比的大小,可以改变音量的大小。
8.音乐渐变效果:在编写程序时,可以使用渐变效果来实现音乐的过渡效果。
通过逐渐增加或减小频率和音量,可以实现音乐渐变的效果,使音乐更加流畅自然。
9.使用音乐库:在单片机编程中,有一些常用的音乐库可以使用。
通过引用这些音乐库,可以简化音乐的编写过程,提高编程效率。
10.节奏变化:在编写程序时,可以尝试在音乐的不同位置加入一些节奏变化,使音乐更加有层次感。
例如,在特定位置加入加速、变慢、停顿等效果。
总结:以上是一些常用的单片机蜂鸣器编程技巧。
通过合理运用这些技巧,可以编写出更多样化、更复杂的音乐效果。
当然,这只是冰山一角,还有很多其他的编程技巧可以尝试,通过对单片机蜂鸣器的深入研究和实践,我们可以更好地掌握这些技巧,创作出独特的音乐作品。
用单片机驱动蜂鸣器的演奏说明

用单片机驱动蜂鸣器演奏的方法说明音的产生是由于物体的振动,通过单片机供电来控制蜂鸣器振动来发声。
单片机IO 口通过高低电平快速切换形成频率可以驱动蜂鸣器发音。
这样蜂鸣器就会以不同的音调“鸣响”。
这里主要理解“音调”和“节拍”两个概念。
音调表示一个音的频率是多少。
即就是音的高低。
在钢琴上,中央C 所在音阶的A ,(C D E F G A B )A 的频率作为基准频率,440Hz 。
同时,需要知道如果f2 = f1*2,则称f2是f1的高八度,即f2和f1的音名相同,高度高了一个音阶。
按照钢琴12平均律,将一个音阶的音均分成12份,那么每一个对应的音都可以计算出确定的频率了。
注意!八度音指频率加倍,将八度音分为12等份,是分为12个等比级数。
f2=f1*2,且f1*12q =f2,可以计算,这个等比数列的比值是q=122=1212=1.05946.为了实现不同音的频率,需要单片机通过定时器不停的产生中断,实现管脚电平反转,来产生相应频率。
这时定时器装载初始值如何计算呢?以标准A 为例,A (f=440Hz),T=1/f=1/440=0.00227273s=2272.73us ,即单片机管脚要输出周期为2272.73us 或者f=440Hz 的方波。
通过单片机定时中断来实现反转的话,考虑单片机定时器装载数值为多少才能形成2272us 的定时中断呢?假设系统时钟8MHz ,则x/8MHz=2272.73us ,x = 18181.1818... x 取整数18181,即定时器应装载18181,才能产生440Hz 的频率。
对应参考表格FIG1.音名 C C# D D# E F F# G G# A A# B 大字组频率f(Hz)65 69 73 78 82 87 92 98 104 110 117 123 周期T(us)15289 14431 13621 12856 12135 11454 10811 10204 9631 9091 8581 8099音名 c c# d d# e f f# g g# a a# b 小字组频率f(Hz)131 139 147 156 165 175 185 196 208 220 233 247 周期T(us)7644 7215 6810 6428 6067 5727 5405 5102 4816 4545 4290 4050音名c1(中央C)c1# d1 d1# e1 f1 f1# g1 g1#a1(基准音)a1# b1小字1组频率f(Hz)262 277 294 311 330 349 370 392 415 440 466 494 周期T(us)3822 3608 3405 3214 3034 2863 2703 2551 2408 2273 2145 2025音名c2 c2# d2 d2# e2 f2 f2# g2 g2# a2 a2# b2 小字2组频率f(Hz)523 554 587 622 659 698 740 784 831 880 932 988 周期T(us)1911 1804 1703 1607 1517 1432 1351 1276 1204 1136 1073 1012音名c3 c3# d3 d3# e3 f3 f3# g3 g3# a3 a3# b3 小字3组频率f(Hz)785 832 881 933 989 1048 1110 1176 1246 1320 1398 1482 周期T(us)1274 1203 1135 1071 1011 954 901 850 803 758 715 675FIG 1.节拍音乐的调号和节拍被表示成 1=C44或者1=G 43,其中的C,或者G 或者位于“=”之后的其他音名表示的意思是,以这个音名作为基础,唱作do 。
单片机蜂鸣器音乐

单片机蜂鸣器音乐单片机在我们的生活中无处不在,它被广泛地应用在各种电子产品中,为我们的生活带来了便利。
今天,我要向大家介绍的是一种基于单片机的蜂鸣器音乐播放器。
一、硬件部分1、单片机:我们选用的是AT89C51单片机,它具有低功耗、高性能的特点,非常适合用于音乐播放器。
2、蜂鸣器:蜂鸣器是用来发出声音的,我们将其连接在单片机的输出口上。
3、存储芯片:为了能够播放存储在芯片中的音乐,我们需要将音乐以某种格式存储在芯片中。
常用的存储芯片有EEPROM和Flash芯片。
4、按键:为了能够选择播放不同的音乐,我们需要添加一个按键。
二、软件部分1、音乐编码:我们需要将音乐转换成二进制编码,这样才能被单片机读取并播放。
常用的音乐编码格式有MIDI、WAV等。
2、音乐播放:当按下按键时,单片机读取存储芯片中的音乐数据,并通过蜂鸣器播放。
3、音乐选择:通过按键可以选择不同的音乐进行播放。
4、音量控制:我们可以通过编程来控制蜂鸣器的音量大小。
三、调试与测试1、硬件调试:检查连接是否正确,确保没有短路或断路的情况。
2、软件调试:将程序下载到单片机中进行调试,确保能够正常播放音乐。
3、综合测试:将所有硬件和软件都连接起来进行测试,确保能够正常工作。
四、总结与展望通过本次实验,我们成功地制作了一个基于单片机的蜂鸣器音乐播放器。
它具有简单、实用的特点,可以用来播放存储在芯片中的音乐。
未来,我们可以进一步扩展其功能,例如添加更多的按键来选择不同的音乐、添加显示屏来显示歌曲名称等。
我们也可以将其应用到其他领域,例如智能家居、智能安防等。
单片机蜂鸣器唱歌程序在许多应用中,单片机蜂鸣器经常被用来发出声音或音乐。
下面是一个使用单片机蜂鸣器唱歌的程序示例。
我们需要确定单片机和蜂鸣器的连接方式。
通常,单片机具有一个内置的蜂鸣器输出引脚,可以将蜂鸣器连接到这个引脚上。
在以下的示例中,我们将假设单片机具有一个内置蜂鸣器输出引脚,并将其连接到P1.0端口上。
51单片机蜂鸣器代码理解

51单片机蜂鸣器代码理解1.引言1.1 概述概述:蜂鸣器是一种广泛应用于电子设备中的声音输出装置,它通过控制某个频率的电信号使蜂鸣器发出特定的声音。
而51单片机,则是一种常见的单片机芯片,具有广泛的应用领域。
本文将主要探讨51单片机蜂鸣器的代码理解和应用。
通过对其基本原理的概述以及相关代码的解析,希望读者能够深入理解51单片机蜂鸣器的工作原理和实现方式。
在第二部分中,我们将介绍单片机蜂鸣器的基本原理。
包括如何通过单片机控制蜂鸣器的电信号频率和时长,从而实现不同的声音效果。
接着,在第二点中,我们将详细解析51单片机蜂鸣器的代码。
通过对代码的分析,读者可以了解到如何使用51单片机的引脚功能和定时器功能来控制蜂鸣器。
最后,在结论部分,我们将对所述内容进行总结,并展望51单片机蜂鸣器在未来的应用前景。
蜂鸣器作为一种重要的声音输出装置,具有广泛的应用前景,可以应用于报警系统、提醒装置等领域。
通过本文的阅读,读者将能够全面了解51单片机蜂鸣器的工作原理和代码实现方式,为相关领域的应用开发提供参考和指导。
让我们开始探索吧!1.2 文章结构文章结构的部分主要介绍了本文的组织和分类方式,以帮助读者更好地理解文章的内容和思路。
本文按照以下结构进行组织:1. 引言部分:介绍了文章的概述、结构和目的。
通过引言部分,读者可以初步了解到本文的内容和主题,并对文章的结构和目的有一个整体的认识。
2. 正文部分:主要分为两个小节,分别是"单片机蜂鸣器的基本原理"和"51单片机蜂鸣器代码解析"。
2.1 单片机蜂鸣器的基本原理:该部分将详细介绍单片机蜂鸣器的基本工作原理,包括蜂鸣器的构成和工作原理,以及单片机如何控制蜂鸣器发出指定的声音。
2.2 51单片机蜂鸣器代码解析:该部分将对51单片机蜂鸣器的代码进行解析,包括如何初始化引脚、设置定时器和中断等相关代码。
通过对代码的逐行解析和说明,读者可以更加深入地理解代码的功能和实现原理。
单片机控制蜂鸣器鸣奏音乐

单片机控制蜂鸣器鸣奏音乐——中北大学:马政贵首先介绍蜂鸣器的发声原理。
我们都知道,音调和音调的时长是音符的主要特征,通过产生不同的音调和音调的时长可以奏出不同的音符来。
然后一个个音符串联在一起就可以产生美妙的音乐来了。
音调主要由声音的频率决定,通过单片机给蜂鸣器不同的音频脉冲来产生不同的音调。
要产生音频脉冲,只要算出某一音频的周期(周期=1/频率),然后将此周期除以2即为半周期的时间。
利用单片机的定时器工作在计数模式MODE1下,设定TH0和TL0的值以产生这半个周期,每当计时到达时就将输出脉冲的I/O(即接蜂鸣器的那个管脚)反相,然后重复计时此半个周期再对I/O反相,就可以在I/O引脚上得到此频率的脉冲。
如果没有必要进行精确的计时,可以用for循环空语句来粗略计时即可(本文选用此法)。
当单片机使用11.0592Mhz的晶振时,for(i=0;i<115;i++);这个空循环延时约为1ms;当晶振选用12Mhz时,可使用for(i=0;i<125;i++);这个空循环来延时1ms。
在这个空循环外头再进行一次循环就可以实现延时若干ms。
如:知道如何产生不同的频率的音调和进行音调的延时的之后,我们便可以编写程序来让单片机控制蜂鸣器来鸣奏音乐了。
下面附上不同音调所对应的频率表:下文介绍了让单片机控制蜂鸣器进行鸣奏音乐的两种方法。
第一种方法是基础的方法,就是顺序地让蜂鸣器挨个地演奏每个音符。
方法一:(此歌曲是《莫斯哥郊外的晚上》的乐曲)#include <reg52.h>sbit fmq=P3^6;void delay(unsigned int a){unsigned char b;while(a--){for(b=0;b<115;b++) ;}}void yanzou(unsigned char i,unsigned int pai){unsigned char y;unsigned int j;for(j=0;j<pai;j++){fmq=0;for(y=0;y<i;y++) ;fmq=1;for(y=0;y<i;y++) ;}}void main(){while(1){yanzou(65,220); //1/2拍中音6yanzou(55,262); //1/2拍高音1yanzou(44,330); //1/2拍高音3yanzou(55,262); //1/2拍高音1yanzou(49,587); //1拍高音2yanzou(55,262); //1/2拍高音1yanzou(58,247); //1/2拍中音7yanzou(44,660); //1拍高音3yanzou(49,587); //1拍高音2yanzou(65,880); //2拍中音6yanzou(55,262); //1/2拍高音1yanzou(44,330); //1/2拍高音3yanzou(37,392); //1/2拍高音5yanzou(37,392); //1/2拍高音5yanzou(65,440); //1拍中音6yanzou(37,392); //1/2拍高音5yanzou(41,349); //1/2拍高音4yanzou(44,2640); //4拍高音3yanzou(41,698); //1拍高音4yanzou(37,784); //1拍高音5yanzou(29,492); //1/2拍高音7yanzou(33,440); //1/2拍高音6yanzou(44,660); //1拍高音3delay(250);yanzou(58,494); //1拍中音7yanzou(65,220); //1/2拍中音6yanzou(44,330); //1/2拍高音3yanzou(49,293); //1/2拍高音2yanzou(41,698); //1拍高音4yanzou(41,698); //1拍高音4yanzou(37,392); //1/2拍高音5yanzou(41,349); //1/2拍高音4yanzou(44,660); //1拍高音3yanzou(49,293); //1/2拍高音2yanzou(55,262); //1/2拍高音1yanzou(44,660); //1拍高音3yanzou(49,587); //1拍高音2yanzou(65,880); //2拍中音6yanzou(65,880); //2拍中音6yanzou(41,698); //1拍高音4yanzou(37,784); //1拍高音5yanzou(29,492); //1/2拍高音7yanzou(33,440); //1/2拍高音6yanzou(44,660); //1拍高音3delay(250);yanzou(58,494); //1拍中音7yanzou(65,220); //1/2拍中音6yanzou(44,330); //1/2拍高音3yanzou(49,293); //1/2拍高音2yanzou(41,698); //1拍高音4yanzou(41,698); //1拍高音4yanzou(37,392); //1/2拍高音5yanzou(41,349); //1/2拍高音4yanzou(44,660); //1拍高音3yanzou(49,293); //1/2拍高音2yanzou(55,262); //1/2拍高音1yanzou(44,660); //1拍高音3yanzou(49,587); //1拍高音2yanzou(65,880); //2拍中音6yanzou(65,880); //2拍中音6delay(5000);}}观察方法一的主函数可以发现,每个语句的形式和实现的功能都是一样的,于是可以想到用数组来进行代码的简化。
单片机蜂鸣器发声原理

单片机蜂鸣器发声原理
单片机蜂鸣器发声原理可以简单描述为以下步骤:
1. 准备工作:首先,需要将蜂鸣器连接到单片机的一个输出口(一般为I/O引脚)。
蜂鸣器有两个引脚,一个为正极(VCC),一个为负极(GND)。
2. 产生方波:在单片机中,通过对蜂鸣器所连接的引脚设置为高电平和低电平之间的快速切换,能够产生一个频率一定、占空比可调节的方波信号。
这个方波信号就是蜂鸣器声音的基准信号。
3. 驱动蜂鸣器:通过不断地将方波信号发送到连接蜂鸣器的引脚,单片机就能够驱动蜂鸣器发出声音。
当方波信号为高电平时,蜂鸣器内部的振膜向前位移,当方波信号为低电平时,蜂鸣器内部的振膜向后位移。
这种间隔的振动就会产生声音。
4. 控制频率和占空比:通过改变方波信号的高电平和低电平之间的时间长度,可以控制蜂鸣器发声的频率和占空比。
频率决定了声音的音调,而占空比则决定了声音的响度和持续时间。
通过上述步骤,单片机可以通过控制蜂鸣器的引脚输出方波信号,从而产生不同频率、不同音调的声音。
这就是单片机蜂鸣器发声的原理。
最新单片机蜂鸣器音乐演奏程序的解释

关于“世上只有妈妈好”的单片机音乐演奏程序2009-11-22 21:45单片机演奏一个音符,是通过引脚,周期性的输出一个特定频率的方波。
这就需要单片机,在半个周期内输出低电平、另外半个周期输出高电平,周而复始。
众所周知,周期为频率的倒数,可以通过音符的频率计算出周期;演奏时,要根据音符的不同,把对应的、半个周期的定时时间初始值,送入定时器,再由定时器按时输出高低电平。
下面是个网上广泛流传的单片机音乐演奏程序,很多人都关心如何修改乐曲的内容,但是不知如何入手。
做而论道对这个软件,做了一些说明,希望对大家有所帮助,以后大家自己就能够编写进去新的乐曲。
在这个程序中,包括了两个数据表,其中存放了事先算好的、各种音符频率所对应的、半周期的定时时间初始值。
有了这些数据,单片机就可以演奏从低音、中音、高音和超高音,四个八度共28个音符。
演奏乐曲时,就根据音符的不同数值,从表中找到定时时间初始值,送入定时器即可控制音调。
乐曲的数据,也要写个数据表:code unsigned char sszymmh[],表中每三个数字,说明了一个音符,它们分别代表:第一个数字是音符的数值1234567之一,代表多来咪发...;第二个数字是0123之一,代表低音、中音、高音、超高音;第三个数字是时间长度,以半拍为单位。
乐曲数据表的结尾是三个0。
#include <reg52.h>sbit speaker = P1^7;unsigned char timer0h, timer0l, time;//--------------------------------------//单片机晶振采用11.0592MHz// 频率-半周期数据表高八位本软件共保存了四个八度的28个频率数据code unsigned char FREQH[] = {0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音12345670xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 2345670xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567// 频率-半周期数据表低八位code unsigned char FREQL[] = {0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音12345670x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567 0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567//--------------------------------------//世上只有妈妈好数据表要想演奏不同的乐曲, 只需要修改这个数据表code unsigned char sszymmh[] = {6, 2, 3, 5, 2, 1, 3, 2, 2, 5, 2, 2, 1, 3, 2, 6, 2, 1, 5, 2, 1,//一个音符有三个数字。
单片机控制蜂鸣器唱歌的原理

单片机控制蜂鸣器唱歌的原理Document serial number【NL89WT-NY98YT-NC8CB-NNUUT-NUT108】一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能象电子琴那样能奏出多种音色的声音。
因此单片机奏乐只需弄清楚两个概念即可,也就是“音调”和“节拍”。
音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间。
1)音调的确定音调就是我们常说的音高。
它是由频率来确定的!我们可以查出各个音符所对应的相应的频率,那么现在就需要我们来用51来发出相应频率的声音!我们常采用的方法就是通过单片机的定时器定时中断,将单片机上对应蜂鸣器的 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 = 12 * (TALL – THL)/ f0 式中TALL = 216= 65536,THL为定时器待确定的计数初值。
因此定时器的高低计数器的初值为:TH =THL/ 256 = ( TALL – t* f0/12) / 256TL = THL % 256 = ( TALL – t* f0/12) %256将t=1136 μs 代入上面两式(注意:计算时应将时间和频率的单位换算一致)即可求出标准音高A 在单片机晶振频率f0=12Mhz,定时器在工作方式1 下的时器高低计数器的予置初值为:TH440Hz = (65536 – 1136 * 12/12) /256 = FBHTL440Hz = (65536 – 1136 * 12/12)%256 = 90H就这样,我们通过延时,发出了我们所需要的频率以单片机12MHZ晶振为例,例出高中低音符与单片机计数T0相关的计数值如下表所示:2)节拍的确定在一张乐谱中,我们经常会看到这样的表达式,如1=C (4/4) 、1=G(3/4) ……等等,这里1=C (4/4),1=G(3/4) 表示乐谱的曲调,和我们前面所谈的音调有很大的关联,4/4、3/4 就是用来表示节拍的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于“世上只有妈妈好”的单片机音乐演奏程序
2009-11-22 21:45
单片机演奏一个音符,是通过引脚,周期性的输出一个特定频率的方波。
这就需要单片机,在半个周期内输出低电平、另外半个周期输出高电平,周而复始。
众所周知,周期为频率的倒数,可以通过音符的频率计算出周期;演奏时,要根据音符的不同,把对应的、半个周期的定时时间初始值,送入定时器,再由定时器按时输出高低电平。
下面是个网上广泛流传的单片机音乐演奏程序,很多人都关心如何修改乐曲的内容,但是不知如何入手。
做而论道对这个软件,做了一些说明,希望对大家有所帮助,以后大家自己就能够编写进去新的乐曲。
在这个程序中,包括了两个数据表,其中存放了事先算好的、各种音符频率所对应的、半周期的定时时间初始值。
有了这些数据,单片机就可以演奏从低音、中音、高音和超高音,四个八度共28个音符。
演奏乐曲时,就根据音符的不同数值,从表中找到定时时间初始值,送入定时器即可控制音调。
乐曲的数据,也要写个数据表:code unsigned char sszymmh[],表中每三个数字,说明了一个音符,它们分别代表:
第一个数字是音符的数值1234567之一,代表多来咪发...;
第二个数字是0123之一,代表低音、中音、高音、超高音;低音:数字下面一个点
中音:没有点
高音:数字上面一个点
超高音:数字上面两个点(两个点纵向排列)
第三个数字是时间长度,以半拍为单位。
音的长短是在音符后面或下面加短横线来表示的。
全音符 5 ———唱四拍
二分音符 5 —唱二拍
四分音符 5 唱一拍
八分音符 5(在音符下加一条短的横线) 唱半拍
十六分音符5(在音符下加两条短的横线)唱四分之一拍
三十二分音符(在音符下加三条短的横线)唱八分之一拍
乐曲数据表的结尾是三个0。
#include <reg52.h>
sbit speaker = P1^7;
unsigned char timer0h, timer0l, time;
//--------------------------------------
//单片机晶振采用11.0592MHz
// 频率-半周期数据表高八位本软件共保存了四个八度的28个频率数据
code unsigned char FREQH[] = {
0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567
0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i
0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567
// 频率-半周期数据表低八位
code unsigned char FREQL[] = {
0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567
0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567
0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567
//--------------------------------------
//世上只有妈妈好数据表要想演奏不同的乐曲, 只需要修改这个数据表code unsigned char sszymmh[] = {
6, 2, 3, 5, 2, 1, 3, 2, 2, 5, 2, 2, 1, 3, 2, 6, 2, 1, 5, 2, 1,
//一个音符有三个数字。
前为第几个音、中为第几个八度、后为时长(以半拍为单位)。
//6, 2, 3代表:6, 中音, 3个半拍;
//5, 2, 1代表:5, 中音, 1个半拍;
//3, 2, 2代表:3, 中音, 2个半拍;
//5, 2, 2代表:5, 中音, 2个半拍;
//1, 3, 2代表:1, 高音, 2个半拍;
//
6, 2, 4, 3, 2, 2, 5, 2, 1, 6, 2, 1, 5, 2, 2, 3, 2, 2, 1, 2, 1,
6, 1, 1, 5, 2, 1, 3, 2, 1, 2, 2, 4, 2, 2, 3, 3, 2, 1, 5, 2, 2,
5, 2, 1, 6, 2, 1, 3, 2, 2, 2, 2, 2, 1, 2, 4, 5, 2, 3, 3, 2, 1,
2, 2, 1, 1, 2, 1, 6, 1, 1, 1, 2, 1, 5, 1, 6, 0, 0, 0};
//--------------------------------------
void t0int() interrupt 1 //T0中断程序,控制发音的音调
{
TR0 = 0; //先关闭T0
speaker = !speaker; //输出方波, 发音
TH0 = timer0h; //下次的中断时间, 这个时间, 控制音调高低
TL0 = timer0l;
TR0 = 1; //启动T0
}
//--------------------------------------
void delay(unsigned char t) //延时程序,控制发音的时间长度
{
unsigned char t1;
unsigned long t2;
for(t1 = 0; t1 < t; t1++) //双重循环, 共延时t个半拍
for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音
TR0 = 0; //关闭T0, 停止发音
}
//--------------------------------------
void song() //演奏一个音符
{
TH0 = timer0h; //控制音调
TL0 = timer0l;
TR0 = 1; //启动T0, 由T0输出方波去发音
delay(time); //控制时间长度
}
//--------------------------------------
void main(void)
{
unsigned char k, i;
TMOD = 1; //置T0定时工作方式1
ET0 = 1; //开T0中断
EA = 1; //开CPU中断
while(1) {
i = 0;
time = 1;
while(time) {
k = sszymmh[i] + 7 * sszymmh[i + 1] - 1;
//第i个是音符, 第i+1个是第几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = sszymmh[i + 2]; //读出时间长度数值
i += 3;
song(); //发出一个音符
}
}
}
//======================================
应网友要求,下面再详细写一下乐谱和数据的转换关系。
以李叔同大师的《送别》的前二小节来说明转换的方法。
这部分的歌词是:“长亭外,古道边,”;
这部分的乐谱是:| 5 35 1 - | 6 16 5 - |。
(注意:乐谱中的1是高音,上边是带点的;还有些音符,应该有下划线,在这里都无法标出。
感兴趣的网友应该去查看正规的乐谱。
)
那么,据此就可以写出《送别》前二小节的数据表:
//--------------------------------------
code unsigned char sszymmh[] = {
5, 2, 2, 3, 2, 1, 5, 2, 1, 1, 3, 4,
//嗦,中音,2个半拍; 咪,中音,1个半拍; 嗦,中音,1个半拍; 哆,高音,4个半拍
6, 2, 2, 1, 3, 1, 6, 2, 1, 5, 2, 4,
//啦,中音,2个半拍; 哆,高音,1个半拍; 啦,中音,1个半拍; 嗦,中音,4个半拍
0, 0, 0};
//结束标记
//--------------------------------------
记住:三个数字一组,代表一个音符。
第一个数字是1234567之一,代表音符哆来咪发...;
第二个数字是0123之一,代表低音、中音、高音、超高音;
第三个数字是半拍的个数,代表时间长度。
当三个数字都是0,就代表乐曲数据表的结尾。
用这个数据表,替换掉程序中《世上只有妈妈好》的数据表,本程序就可以播放《送别》的前两小节。