单片机利用定时器和蜂鸣器唱歌
单片机蜂鸣器唱歌程序(二)2024
单片机蜂鸣器唱歌程序(二)引言概述:本文档主要介绍了单片机蜂鸣器唱歌程序(二),包括使用单片机控制蜂鸣器发出不同音乐的方法和具体实现步骤。
本文将从五个大点进行阐述,每个大点包含5-9个小点,以便读者更好地理解和实践。
正文:一、引脚连接设置1. 确定单片机的输出引脚和蜂鸣器的输入引脚2. 将单片机的输出引脚与蜂鸣器的输入引脚连接3. 确保连接的稳定性和正确性4. 利用电路图进行布线二、编程环境配置1. 安装适合单片机的编程软件2. 创建新的项目3. 配置单片机的型号及选项4. 导入相关的库文件5. 编写代码框架三、发声原理及代码实现1. 理解蜂鸣器工作原理2. 使用单片机的PWM输出功能控制蜂鸣器的频率3. 利用PWM输出的方式实现不同音调的发声4. 编写音调转换函数5. 编写歌曲的音乐片段代码四、优化和调试1. 测试不同频率的声音2. 调整蜂鸣器的音量3. 避免噪音的干扰4. 检查代码的正确性和合理性5. 不断尝试,优化代码和音效五、实验结果及总结1. 运行程序,测试蜂鸣器的唱歌效果2. 记录实验结果和观察结果3. 分析实验过程中遇到的问题和解决方法4. 总结实验经验和注意事项5. 展望将来的改进和研究方向总结:本文详细介绍了单片机蜂鸣器唱歌程序(二)的实现方法和步骤。
通过连接设置、编程环境配置、发声原理及代码实现、优化和调试、实验结果及总结等五个大点的阐述,读者可以深入了解单片机控制蜂鸣器发声的原理和方法,并通过实验得到具体的唱歌效果。
同时,读者在实践过程中也要注意优化和调试,不断尝试和改进,以实现更好的音效效果。
希望本文对读者有所帮助,为单片机蜂鸣器唱歌程序的开发提供了指导和参考。
单片机课程设计报告(利用蜂鸣器播放音乐)
课程设计:嵌入式系统应用题目名称:利用蜂鸣器实现音乐播放功能姓名:学号:班级:完成时间:1设计的任务设计内容:动手焊接一个51单片机设计目标:利用单片机上的蜂鸣器实现音乐播放功能2 设计的过程2.1 基本结构1.STC89C52RC在本次的试验中采用了STC89C52RC单片机,STC89C52RC单片机是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机,指令代码完全兼容传统8051单片机,12时钟/机器周期,工作电压:5.5V~3.3V(5V单片机)/3.8V~2.0V(3V单片机),工作频率范围:0~40MHz,相当于普通8051的0~80MHz,实际工作频率可达48MHz,用户应用程序空间为8K字节。
(STC89C52RC引脚图)STC89C52RC单片机的工作模式:(1)典型功耗<0.1μA,可由外部中断唤醒,中断返回后,继续执行原程序(2)空闲模式:典型功耗2mA(3)正常工作模式:典型功耗4Ma~7mA(4)唤醒,适用于水表、气表等电池供电系统及便携设备2.蜂鸣器及其工作原理:蜂鸣器按其结构分主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场,振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。
本实验采用的是电磁式蜂鸣器。
蜂鸣器按其是否带有信号源又分为有源和无源两种类型。
有源蜂鸣器只需要在其供电端加上额定直流电压,其内部的震荡器就可以产生固定频率的信号,驱动蜂鸣器发出声音。
无源蜂鸣器可以理解成与喇叭一样,需要在其供电端上加上高低不断变化的电信号才可以驱动发出声音。
本实验采用的是有源蜂鸣器。
(蜂鸣器与单片机连接电路图)2.2 软件设计过程1.蜂鸣器发声原理本实验由于采用有源蜂鸣器,只需将引脚端口P3^4清零,蜂鸣器即可发声;P3^4置位,蜂鸣器停止发声。
51单片机蜂鸣器播放单音节音乐
0xFD,0x23,0x7F, 0xFC,0xAC,0x7F, 0xFD,0x23,0xFF, 0xFC,0x44,0xFF,
// 1_ 3_ 2 .5
0xFC,0x44,0x7F, 0xFD,0x23,0x7F, 0xFC,0xAC,0xFF, 0xFA,0x68,0xFF,
{
for (i =0; i < 363; i++)
{;}
}
}
*名称:Init()
*功能:设置计数器0工作方式,16位计数,溢出中断方式
**********************************************************************************/
void Init()
{
TMOD = 0x01; //定时器0处于计时方式,16位
*名称:Count1(void) interrupt 1
*功能:设置计时器0溢出中断,每中断一次改变P2_3引脚电平
*********************************************************************************/
void Count1(void) interrupt 1
void main()
{
uchar time;
Init();
TH0 = high;
TL0 = low;
while (1)
{
if (music[ptr] != 0xFF && music[ptr] != 0x00)//判断是否是正常音符
{
TR0 = 0;
P2_3 = 1;
单片机蜂鸣器编程技巧
单片机蜂鸣器编程技巧1.音乐节奏控制:在编写程序时,可以使用定时器来控制蜂鸣器的音符持续时间。
通过调整定时器的参数值,可以实现不同音长的音符,从而控制节奏感。
2.音符频率控制:不同音符具有不同的频率,可以根据乐谱中各个音符的频率,将其对应的频率值存储在一个数组中。
通过控制蜂鸣器输出的频率,可以实现不同音高的音符。
3.延时函数:在单片机编程中,经常需要使用延时函数来控制时间间隔。
在输出音乐时,可以通过延时函数控制每个音符的持续时间。
通过调整延时函数的参数值,可以实现不同音符间的时间间隔,从而实现更好听的音乐效果。
4.音乐合奏:在编写程序时,可以将不同乐器的音符同时输出到不同的蜂鸣器上,从而实现多个乐器的合奏效果。
通过合理地组合不同乐器的频率和节奏,可以编写出更丰富的音乐作品。
5.音乐循环播放:通过编写循环结构,可以实现音乐循环播放的效果。
通过精确地确定循环次数,可以实现指定音乐节拍的循环播放效果。
6.音乐速度调节:通过调整延时函数的参数值,可以控制音乐的播放速度。
加快延时时间可以使音乐播放加速,减慢延时时间可以使音乐放慢。
7.音乐音量控制:通过控制蜂鸣器输出的PWM信号的占空比,可以实现音乐的音量控制。
调整PWM信号占空比的大小,可以改变音量的大小。
8.音乐渐变效果:在编写程序时,可以使用渐变效果来实现音乐的过渡效果。
通过逐渐增加或减小频率和音量,可以实现音乐渐变的效果,使音乐更加流畅自然。
9.使用音乐库:在单片机编程中,有一些常用的音乐库可以使用。
通过引用这些音乐库,可以简化音乐的编写过程,提高编程效率。
10.节奏变化:在编写程序时,可以尝试在音乐的不同位置加入一些节奏变化,使音乐更加有层次感。
例如,在特定位置加入加速、变慢、停顿等效果。
总结:以上是一些常用的单片机蜂鸣器编程技巧。
通过合理运用这些技巧,可以编写出更多样化、更复杂的音乐效果。
当然,这只是冰山一角,还有很多其他的编程技巧可以尝试,通过对单片机蜂鸣器的深入研究和实践,我们可以更好地掌握这些技巧,创作出独特的音乐作品。
从零开始学单片机(八)蜂鸣器唱歌
1,2,2, 1,2,2, 5,2,2, 5,2,2, 6,2,2, 6,2,2, 5,2,4, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,2, 2,2,2, 1,2,4, 5,2,2, 5,2,2, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,4, 5,2,2, 5,2,2, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,4, 1,2,2, 1,2,2, 5,2,2, 5,2,2, 6,2,2, 6,2,2, 5,2,4, 4,2,2, 4,2,2, 3,2,2, 3,2,2, 2,2,2, 2,2,2, 1,2,4 }; //定时器计时初值,高八位,代表不同音符的频率 code unsigned char FREQH[]={ 0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC, 0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;
delay(duration); }
{ unsigned int i; unsigned char j=80; for(i=0; i while(j--); TR0=0; } void song() { TH0 = byteTH0; TL0 = byteT0L; TR0 = 1;
ET0=1; while(1) { step=0; while(step<126) { index = music[step] + 7 * music[step+1] - 1; byteTH0 = FREQH[index]; byteT0L = FREQL[index]; duration = music[step+2]; step += 3; song();
基于c51单片机编写简单蜂鸣器音乐程序的方法
uint i;
for(i=0;i<jp;i++)
{
sound(s);
if(s==0xff)break;
}
}
//*******************************************************************
void main()//主函数
{
while(1)
{
c=0;//用来使数组从头开始读取
/*3*/case 0x0d:j=s/330;break;case 0x0e:j=s/659;break;case 0x0f:j=s/1318;break;
/*4*/case 0x10:j=s/349;break;case 0x11:j=s/370;break;case 0x12:j=s/698;break;case 0x13:j=s/740;break;case 0x14:j=s/1379;break;case 0x15:j=s/1480;break;
0x01,0x0d,0x16,0x1c,0xff,0x1c,0x1c,0x16,0x07,0x07,0x10,0x0d,0xff, 0x01,0x0d,0x16,0x1c,0xff,
0x1c,0x1c,0x22,0x1c,0x16,0x10,0x0d,0x10,0x0d,0x07,0x01,0x00} ;//*
uint code music[]=//这是一个“童话”谱子的数组,与m_t()子程序中的十六进制数一一对应,0xff代表每次音乐的停顿,0x00表示音乐的结束
{0x16,0x10,0x0d,0xff, 0x0d,0x10,0x0d, 0xff, 0x0d,0x10,0x0d,0x10,0x0d,0x07,0x01,0xff,
单片机控制蜂鸣器鸣奏音乐
单片机控制蜂鸣器鸣奏音乐——中北大学:马政贵首先介绍蜂鸣器的发声原理。
我们都知道,音调和音调的时长是音符的主要特征,通过产生不同的音调和音调的时长可以奏出不同的音符来。
然后一个个音符串联在一起就可以产生美妙的音乐来了。
音调主要由声音的频率决定,通过单片机给蜂鸣器不同的音频脉冲来产生不同的音调。
要产生音频脉冲,只要算出某一音频的周期(周期=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);}}观察方法一的主函数可以发现,每个语句的形式和实现的功能都是一样的,于是可以想到用数组来进行代码的简化。
单片机课程设计报告利用蜂鸣器播放音乐样本
课程设计: 电子设计题目名称: 音乐流水灯姓名: 戴锦超学号: 08123447班级: 信科12-3班完成时间: 10月23日1设计的任务设计内容: 动手焊接一个51单片机设计目标: 利用单片机上的蜂鸣器以及二极管实现音乐播放以及根据音乐的节奏而规律性闪亮的二极管。
而且经过程序调节音乐节奏的快慢。
2 设计的过程2.1 基本结构1.STC89C52RC在本次的试验中采用了STC89C52RC单片机, STC89C52RC 单片机是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机, 指令代码完全兼容传统8051单片机, 12时钟/机器周期, 工作电压: 5.5V~3.3V( 5V单片机) /3.8V~2.0V( 3V单片机) , 工作频率范围: 0~40MHz, 相当于普通8051的0~80MHz, 实际工作频率可达48MHz, 用户应用程序空间为8K字节。
( STC89C52RC引脚图)STC89C52RC单片机的工作模式:(1)典型功耗<0.1μA,可由外部中断唤醒, 中断返回后, 继续执行原程序(2)空闲模式: 典型功耗2mA(3)正常工作模式: 典型功耗4Ma~7mA( 4) 唤醒, 适用于水表、气表等电池供电系统及便携设备2.蜂鸣器及其工作原理:蜂鸣器按其结构分主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后, 振荡器产生的音频信号电流经过电磁线圈, 使电磁线圈产生磁场, 振动膜片在电磁线圈和磁铁的相互作用下, 周期性地振动发声。
本实验采用的是电磁式蜂鸣器。
蜂鸣器按其是否带有信号源又分为有源和无源两种类型。
有源蜂鸣器只需要在其供电端加上额定直流电压, 其内部的震荡器就能够产生固定频率的信号, 驱动蜂鸣器发出声音。
无源蜂鸣器能够理解成与喇叭一样, 需要在其供电端上加上高低不断变化的电信号才能够驱动发出声音。
本实验采用的是有源蜂鸣器。
STM32F103通用定时器PWM应用例程--蜂鸣器演奏乐曲
STM32F103通用定时器PWM应用例程:蜂鸣器演奏乐曲一.说明:本例程是将流明LM3SLib_Timer.pdf文档中的例程9及例程10(PWM应用:蜂鸣器演奏乐曲),移植到STM32F103上。
二.流明LM3SLib_Timer.pdf例程9及例程10的拷贝:例程9.Timer PWM应用:蜂鸣器发声如图1.1所示,为EasyARM1138开发板上的蜂鸣器驱动电路。
蜂鸣器类型是交流蜂鸣器,也称无源蜂鸣器,需要输入一列方波才能鸣响,发声频率等于驱动方波的频率。
图1.1 蜂鸣器驱动电路程序清单1.9是Timer模块16位PWM模式的一个应用,可以驱动交流蜂鸣器发声,运行后蜂鸣器以不同的频率叫两声。
其中"buzzer.h"和"buzzer.c"是蜂鸣器的驱动程序,仅有3个驱动函数,用起来很简捷。
程序清单1.9 Timer PWM应用:蜂鸣器发声文件:main.c#include "systemInit.h"#include "buzzer.h"// 主函数(程序入口)int main(void){jtagWait(); // 防止JTAG失效,重要!clockInit(); // 时钟初始化:晶振,6MHzbuzzerInit(); // 蜂鸣器初始化buzzerSound(1500); // 蜂鸣器发出1500Hz声音SysCtlDelay(400* (TheSysClock / 3000)); // 延时约400msbuzzerSound(2000); // 蜂鸣器发出2000Hz声音SysCtlDelay(800* (TheSysClock / 3000)); // 延时约800msbuzzerQuiet( ); // 蜂鸣器静音for (;;){}}文件:buzzer.h#ifndef __BUZZER_H__#define __BUZZER_H__// 蜂鸣器初始化extern void buzzerInit(void);// 蜂鸣器发出指定频率的声音extern void buzzerSound(unsigned short usFreq);// 蜂鸣器停止发声extern void buzzerQuiet(void);#endif // __BUZZER_H__文件:buzzer.c#include "buzzer.h"#include <hw_types.h>#include <hw_memmap.h>#include <sysctl.h>#include <gpio.h>#include <timer.h>#define PART_LM3S1138#include <pin_map.h>#define SysCtlPeriEnable SysCtlPeripheralEnable#define GPIOPinTypeOut GPIOPinTypeGPIOOutput// 声明全局的系统时钟变量extern unsigned long TheSysClock;// 蜂鸣器初始化void buzzerInit(void){SysCtlPeriEnable(SYSCTL_PERIPH_TIMER1); // 使能TIMER1模块SysCtlPeriEnable(CCP3_PERIPH); // 使能CCP3所在的GPIO端口GPIOPinTypeTimer(CCP3_PORT, CCP3_PIN); // 设置相关管脚为Timer功能TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | // 配置TimerB为16位PWM TIMER_CFG_B_PWM);}// 蜂鸣器发出指定频率的声音// usFreq是发声频率,取值(系统时钟/65536)+1 ~20000,单位:Hzvoid buzzerSound(unsigned short usFreq){unsigned long ulVal;if ((usFreq <= TheSysClock / 65536UL) || (usFreq > 20000)){buzzerQuiet( );}else{GPIOPinTypeTimer(CCP3_PORT, CCP3_PIN); // 设置相关管脚为Timer功能ulVal = TheSysClock / usFreq;TimerLoadSet(TIMER1_BASE, TIMER_B, ulVal); // 设置TimerB初值TimerMatchSet(TIMER1_BASE, TIMER_B, ulVal / 2); // 设置TimerB匹配值TimerEnable(TIMER1_BASE, TIMER_B); // 使能TimerB计数}}// 蜂鸣器停止发声void buzzerQuiet(void){TimerDisable(TIMER1_BASE, TIMER_B); // 禁止TimerB计数GPIOPinTypeOut(CCP3_PORT, CCP3_PIN); // 配置CCP3管脚为GPIO输出GPIOPinWrite(CCP3_PORT, CCP3_PIN, 0x00); // 使CCP3管脚输出低电平}例程10.Timer PWM应用:蜂鸣器演奏乐曲程序清单1.10是Timer模块16位PWM模式的一个应用,能驱动交流蜂鸣器演奏一首动听的乐曲《化蝶》(乐谱参见图1.2)。
单片机教程实战2_蜂鸣器唱歌
单片机教程实战2 蜂鸣器唱歌发布: 2009-11-04 09:01 | 作者: 平凡 | 来源: 网络 | 查看: 189次利用单片机(或单板机)奏乐大概是无线电爱好者感兴趣的问题之一。
本文从单片机的基本发间实验出发,谈谈音乐程序的设计原理,并给出具体实例,以供参考。
单片机的基本发音实验我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单处机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的矩形波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。
例如,要产生200HZ的音频信号,按图1接入喇叭(若属临时实验,也可将喇叭直接接在P1口线上),实验程序为:其中子程序DEL为延时子程序,当R3为1时,延时时间约为20us,R3中存放延时常数,对200HZ音频,其周期为1/200秒,即5ms。
这样,当P1.4的高电平或低电平的持续时间为2.5ms,即R3的时间常数取2500/20=125(7DH)时,就能发出200HZ 的音调。
将上述程序键入学习机,并不断修改R3的常数可以感到音调的变化。
乐曲中,每一音符对应着确定的频率,表1给出C调时各音符频率及其相应的时间常数。
读者可以根据表1所提供的常数,将其16进制代码送入R3,反复练习体会。
根据表1可以奏出音符。
仅这还不够,要准确奏出一首曲子,必须准确地控制乐曲节奏,即一音符的持续时间。
音符的节拍我们可以用定时器T0来控制,送入不同的初值,就可以产生不同的定时时间。
便如某歌曲的节奏为每分钟94拍,即一拍为0.64秒。
其它节拍与时间的对应关系见表2。
但时,由于T0的最大定时时间只能为131毫秒,因此不可能直接用改变T0的时间初值来实现不同节拍。
我们可以用T0来产生10毫秒的时间基准,然后设置一个中断计数器,通过判别中断计数器的值来控制节拍时间的长短。
表2中也给出了各种节拍所对应的时间常数。
单片机-利用蜂鸣器演奏音乐
实验三-利用蜂鸣器演奏音乐一、实验目的1.了解BlueSkyC51单片机实验板中蜂鸣器的硬件电路2.学会利用蜂鸣器实现音乐的演奏3.掌握蜂鸣器实现音乐演奏的编程二、实验硬件设计及电路1. BlueSkyC51单片机实验板2.单片机最小系统3.蜂鸣器电路连接三极管主要是做驱动用的。
因为单片机的IO口驱动能力不够让蜂鸣器发出声音,所以我们通过三极管放大驱动电流,从而可以让蜂鸣器发出声音,你要是输出高电平,三极管导通,集电极电流通过蜂鸣器让蜂鸣器发出声音,当输出低电平时,三极管截止,没有电流流过蜂鸣器,所以就不会发出声音。
三、实验原理1.音调及节拍用一个口,输出方波,这个方波输入进蜂鸣器就会产生声音,通过控制方波的频率、时间,就能产生简单的音乐。
一般说来,单片机演奏音乐基本都是单音频率,因此单片机奏乐只需控制音调和节拍。
(1)音调的确定音调是由频率来确定的。
通过单片机的定时器定时中断,将单片机上对应蜂鸣器的I/O 口来回取反,从而让蜂鸣器发出不同频率的声音。
只需将定时器给以不同的定时值就可实现。
通过延时,即可发出所需要的频率。
(2)节拍的确定一拍的时长大约为400—500ms,每个音符的时长通过节拍来计算。
详细见程序代码。
2.软件设计相关(1)头文件#include<reg51.h>#define uint unsigned int#define uchar unsigned char#define ulong unsigned longsbit beep=P1^4; //蜂鸣器与P1.4口连接(2)歌曲曲谱uchar code diaodata[30]={ //音调代码0x10,0x0e,0x0c,0x10,0x0e,0x0c,0x10,0x0e,0x10,0x0c,0x10,0x15,0x13,0x10,0x13,0x15,0x15,0x13,0x15,0x13,0x10,0x0e,0x0c,0x0e,0x0e,0x10,0x0e,0x0c,0x0e,0x00};uchar code jiedata[30]={ //音长代码0x04,0x04,0x08,0x06,0x02,0x08,0x04,0x04,0x04,0x04,0x02,0x06,0x08,0x02,0x02,0x04,0x04,0x04,0x04,0x08,0x02,0x02,0x04,0x04,0x02,0x02,0x04,0x04,0x0c,0x00};(3)音阶表uchar code freq[36*2]={ //音阶码表0xf7,0xd8, //440hz , 1 //00xf8,0x50, //466hz , 1# //10xf8,0xbc, //494hz , 2 //20xf9,0x26, //524hz , 2# //30xf9,0x85, //554hz , 3 //40xf9,0xe5, //588hz , 4 //50xfa,0x3d, //622hz , 4# //60xfa,0x92, //660hz , 5 //70xfa,0xdd, //698hz , 5# //80xfb,0x29, //740hz , 6 //90xfb,0x70, //784hz , 6# //100xfb,0xb0, //830hz , 7 //110xfb,0xef, //880hz , 1 //120xfc,0x29, //932hz , 1# //130xfc,0x62, //988hz , 2 //140xfc,0x95, //1046hz, 2# //150xfc,0xc7, //1108hz, 3 //160xfc,0xf5, //1174hz, 4 //170xfd,0x20, //1244hz, 4# //180xfd,0x4c, //1318hz, 5 //190xfd,0x72, //1396hz, 5# //200xfd,0x97, //1480hz, 6 //210xfd,0xbb, //1568hz, 6# //220xfd,0xdc, //1662hz, 7 //230xfd,0xfb, //1769hz, `1 //240xfe,0x18, //1864hz, `1# //250xfe,0x34, //1976hz, `2 //260xfe,0x4e, //2092hz, `2# //270xfe,0x67, //2218hz, `3 //280xfe,0x7d, //2350hz, `4 //290xfe,0x94, //2488hz, `4# //300xfe,0xa8, //2639hz, `5 //310xfe,0xbc, //2794hz, `5# //320xfe,0xcf, //2960hz, `6 //330xfe,0xe0, //3136hz, `6# //340xfe,0xf1, //3322hz, `7 //35};(4) 音符发生程序(中断服务程序)void timer0() interrupt 1 //用于产生音符的T0中断服务程序{TH0=th0_f;TL0=tl0_f;beep=~beep; //取反beep引脚,发声}三、实验过程及问题1.Keil开发过程(1)新建“Project”,选择单片机为“AT89C52”(2)新建c文件“music.c”,并添加到工程中(3)设置生成“HEX”文件,编译(4)将生成的“HEX”文件烧录到单片机,检验(5)不断修改完善2.编译实验相关问题(1)实际发音颤音重解决方法为修改蜂鸣器的驱动频率.(2)实际节奏过快或者过慢调整延时四、C51程序代码(部分来源于网络)#include<reg51.h>#define uint unsigned int#define uchar unsigned char#define ulong unsigned longsbit beep=P1^4; //蜂鸣器与P1.4口连接uchar th0_f; //中断装载T0高8位uchar tl0_f; //T0低8位uchar code freq[36*2]={ //音阶码表0xf7,0xd8, //440hz , 1 //00xf8,0x50, //466hz , 1# //10xf8,0xbc, //494hz , 2 //20xf9,0x26, //524hz , 2# //30xf9,0x85, //554hz , 3 //40xf9,0xe5, //588hz , 4 //50xfa,0x3d, //622hz , 4# //60xfa,0x92, //660hz , 5 //70xfa,0xdd, //698hz , 5# //80xfb,0x29, //740hz , 6 //90xfb,0x70, //784hz , 6# //100xfb,0xb0, //830hz , 7 //110xfb,0xef, //880hz , 1 //120xfc,0x29, //932hz , 1# //130xfc,0x62, //988hz , 2 //140xfc,0x95, //1046hz, 2# //150xfc,0xc7, //1108hz, 3 //160xfc,0xf5, //1174hz, 4 //170xfd,0x20, //1244hz, 4# //180xfd,0x4c, //1318hz, 5 //190xfd,0x72, //1396hz, 5# //200xfd,0x97, //1480hz, 6 //210xfd,0xbb, //1568hz, 6# //220xfd,0xdc, //1662hz, 7 //230xfd,0xfb, //1769hz, `1 //240xfe,0x18, //1864hz, `1# //250xfe,0x34, //1976hz, `2 //260xfe,0x4e, //2092hz, `2# //270xfe,0x67, //2218hz, `3 //280xfe,0x7d, //2350hz, `4 //290xfe,0x94, //2488hz, `4# //300xfe,0xa8, //2639hz, `5 //310xfe,0xbc, //2794hz, `5# //320xfe,0xcf, //2960hz, `6 //330xfe,0xe0, //3136hz, `6# //340xfe,0xf1, //3322hz, `7 //35};uchar code diaodata[30]={ //音调代码0x10,0x0e,0x0c,0x10,0x0e,0x0c,0x10,0x0e,0x10,0x0c,0x10,0x15,0x13,0x10,0x13,0x15,0x15,0x13,0x15,0x13,0x10,0x0e,0x0c,0x0e,0x0e,0x10,0x0e,0x0c,0x0e,0x00};uchar code jiedata[30]={ //音长代码0x04,0x04,0x08,0x06,0x02,0x08,0x04,0x04,0x04,0x04,0x02,0x06,0x08,0x02,0x02,0x04,0x04,0x04,0x04,0x08,0x02,0x02,0x04,0x04,0x02,0x02,0x04,0x04,0x0c,0x00};void timer0() interrupt 1 //用于产生音符的T0中断服务程序{TH0=th0_f;TL0=tl0_f;beep=~beep; //取反beep引脚,发声}void main(void){uchar i,j,k=0;uint n;TMOD=0X01; //T0方式1TR0=0; //关闭T0(不发声)ET0=1; //允许T0中断EA=1; //允许总中断while(1){TR0=1; //开T0for(i=0;diaodata[i]!=0;i++){th0_f=freq[diaodata[i]*2];tl0_f=freq[diaodata[i]*2+1];for(j=0;j<20000;n++); //(jiedata*20000)TR0=0;for(n=0;n<256;n++); //音符之间的短暂延时TR0=1;}TR0=0;}}(注:可编辑下载,若有不当之处,请指正,谢谢!)。
单片机蜂鸣器音乐代码
单片机蜂鸣器音乐代码在单片机的应用中,蜂鸣器是一个常用的音频输出设备。
它可以通过产生不同频率的声音来实现音乐播放、提醒和警报等功能。
本文将介绍如何使用单片机控制蜂鸣器播放音乐,并提供一个简单的音乐代码示例。
首先,让我们了解一下单片机蜂鸣器的工作原理。
蜂鸣器实际上是一个压电陶瓷元件,当电压作用于其上时,它会振动产生声音。
为了产生不同的音调,我们需要控制蜂鸣器的频率和占空比。
单片机通过IO口与蜂鸣器连接,并使用定时器来产生所需的频率。
具体的代码实现将依赖于使用的单片机型号和开发环境。
在这里,我们将以C语言为例,并基于51单片机进行说明。
以下是一个简单的单片机蜂鸣器音乐代码示例,演奏的是《欢乐颂》的前几个音符:```c#include <reg52.h>// 定义各个音符的频率#define C4 4778#define D4 4257#define E4 3792#define F4 3579#define G4 3189#define A4 2841#define B4 2531#define C5 2388// 延时函数void delay(unsigned int count){while(count--);}// 发声函数void beep(unsigned int frequency, unsigned int duration) {unsigned int i;unsigned long time;time = 11059200 / frequency; time >>= 1;for(i = 0; i < duration; i++) {P1 = 0x08;delay(time);P1 = 0x00;delay(time);}}// 主函数void main(){// 设置定时器TMOD = 0x01;TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; TR0 = 1;// 播放音乐beep(C4, 100);beep(D4, 100);beep(E4, 100);beep(F4, 100);beep(G4, 100);beep(A4, 100);beep(B4, 100);beep(C5, 100);while(1);}```以上代码中,我们首先定义了各个音符的频率,这些频率是通过实验测量得到的,具体数值可能因蜂鸣器型号、电源电压等因素而略有差异。
蜂鸣器唱歌程序
蜂鸣器唱歌----生日快乐下面是我单片机入门的时候写的一个蜂鸣器唱歌的程序,用的是stc89c52的单片机和12MHZ的晶振。
它大致是这样工作的。
我们知道歌曲都是由最基本的音调和节拍组成的。
音调就是该音符的频率,节拍就是该音符持续的时间。
也就是说发出一个最基本的音我们需要两个参数,一个是频率,一个是节拍。
那么在单片机中如何产生这两个参数呢?首先我们需要知道该音符的频率,然后用单片机的I/O口不断地变高变低来产生这个频率。
比如 1 这个音在低音,中音,高音三种情况下会有3种频率,至于到底是哪种音,在歌曲的乐谱中会给出详细的标识。
现在我们假设1 这个音为低音,在d调(什么是d调?看文章尾附录)下频率为293hz,一个周期为T=1/293 s。
那么I/O口被置1和置0的时间各占一半也就是T/2。
然后算出相应的定时器初值,那么单片机就可以发出这个音了。
接下来就是一个音符要唱多久,那就要看这个音符占据多少个节拍了,同样在歌曲的乐谱中会给出详细的标示。
那么一拍是多长呢,下面有说明。
慢节奏一般600ms一拍,快节奏一般400ms一拍。
如果你要知道更准确的节拍时长,只有拿着乐谱去听歌了,记下唱一拍的时间就行了。
我用的是定时器0控制节拍长度,在每个音符开始时开启它,它是10ms 中断一次,并且让里面的计数值增加1。
如果我要唱一拍的话(假设为600ms),那么我只需要判断计数值是否达到60,如果达到那么就停止计时然后跳到下一拍。
以上就是蜂鸣器唱歌的基本原理了,希望能对你有所帮助。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit sound=P3^7;uint counter=0;uchar code FREQH[3][8]= //音符定时器初值,三个8度音的高八位{//注意每行起始都为0xff,因为音调中没有0 这个音,所以随便填了个数字,后面不不会引用它// 低音:// 1 2 3 4 5 6 7{0xff,0xf9, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc},//中音://1 2 3 4 5 6 7{0xff,0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe},//高音://1 2 3 4 5 6 7{0xff,0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0x00}//0x00};uchar code FREQL[3][8]= //音符定时器初值,三个8度音的低八位{// 低音:// 1 2 3 4 5 6 7{0xff,0x5b, 0x15, 0xb9, 0x04, 0x90, 0x0c, 0x79},//中音:// 1 2 3 4 5 6 7{0xff,0xac, 0x09, 0x5c, 0x82, 0xc8, 0x05, 0x3c},//高音://1 2 3 4 5 6 7{0xff,0x55, 0x84, 0xad, 0xc0, 0xe3, 0x02, 0x00}//0x00};uchar code MUSIC[]={//生日快乐//歌曲代码,每三个表示一个音符及节拍,第一个表示音符1234567,第二个表示音高,0表示低音,1表示中音,2表示高音,第三个表示节拍长度,1表示半拍,2表示一拍,以此类推。
(完整word版)单片机控制蜂鸣器唱歌的原理
一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能象电子琴那样能奏出多种音色的声音。
因此单片机奏乐只需弄清楚两个概念即可,也就是“音调"和“节拍"。
音调表示一个音符唱多高的频率,节拍表示一个音符唱多长的时间。
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 就是用来表示节拍的。
基于单片机的蜂鸣器唱歌设计(附图)
蜂鸣器是一种一体化结构的电子讯响器�主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型�他广泛应用于计算机、打印机、复印机、报警器、电话机等电子产品中作发声器件。
单片机上面使用的蜂鸣器一般都是无源电磁式的蜂鸣器�如下图所示�。
它由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
接通电源后�振荡器产生的音频信号电流通过电磁线圈�使电磁线圈产生磁场�振动膜片在电磁线圈和磁铁的相互作用下�周期性地振动发声。
蜂鸣器发声原理是电流通过电磁线圈�使电磁线圈产生磁场来驱动振动膜发声的�因此需要一定的电流才能驱动它�单片机IO引脚输出的电流较小�单片机输出的TTL电平基本上驱动不了蜂鸣器�因此需要增加一个电流放大的电路。
单片机与蜂鸣器连接如图二所示。
图中�蜂鸣器的正极接到VCC��5V�电源上面�蜂鸣器的负极接到三极管的发射极E�三极管的基级B经过限流电阻R1后由单片机的P3.7引脚控制�当P3.7输出高电平时�三极管T1截止�没有电流流过线圈�蜂鸣器不发声�当P3.7输出低电平时�三极管导通�这样蜂鸣器的电流形成回路�发出声音。
因此�我们可以通过程序控制P3.7脚的电平来使蜂鸣器发出声音和关闭。
程序中改变单片机P3.7引脚输出波形的频率�就可以调整控制蜂鸣器音调�产生各种不同音色、音调的声音。
另外�改变P3.7输出电平的高低电平占空比�则可以控制蜂鸣器的声音大小�这些我们都可以通过编程实验来验证。
下面就是一个能够发出音乐的单片机程序�示例中所播放的音乐是《两只老虎》。
SPK EQU P3.7 ;位定义ORG 0000H ;伪指令�指定程序从0000H开始存放LJMP START ;程序跳转至START处执行ORG 0030H ;伪指令�指定程序从0030H开始存放START: MOV SP,#60H ;堆栈初始化MOV R3,#00H ;给R3赋值NEXT:MOV A,R3MOV DPTR,#TABLE ;查歌曲表MOVC A,@A+DPTRJZ START ;为00则循环播放此歌MOV R7,A ;R7/R2保存连续相邻的表数据INC R3MOV A,R3MOVC A,@A+DPTRMOV R2,AACALL SONGINC R3SJMP NEXT;==============================;=========歌曲播放子程序==========;==============================SONG:MOV A,R2 ;取出节拍RL AJNZ KEEP ;A不等于零则跳MOV A,#01H ;A等于零则赋值为1KEEP:MOV R2,A ;REPEAT:ACALL EIGHTH ;调用1/8拍延时程序DJNZ R2,REPEAT ;RET;===============================;=======产生1/8拍延时子程序=======;===============================EIGHTH:MOV A,R7 ;查表取出延时参数,保存到R4MOV DPTR,#DELAY_TMOVC A,@A+DPTRMOV R4,AMOV A,R7 ;查表取出1/8拍周期数,保存到R5 MOV DPTR,#S_PARAMOVC A,@A+DPTRMOV R5,ANEXTCYC:ACALL SOUNDDJNZ R5,NEXTCYCRET;==============================;===========发声子程序===========;==============================SOUND:SETB SPKACALL SDELAYCLR SPKACALL SDELAYRET;==============================;===========延时子程序===========;==============================SDELAY:MOV A,R4 ;延时值在R4内MOV R0,AXL2:MOV R1,#03HDL1:NOPDJNZ R1,DL1DJNZ R0,XL2RET;==============================;===========1/8拍周期表==========;==============================S_PARA:DS 1DHDB 15H,16H,00DB 19H,00H,1CH,00H,1FH,21H,00H,25HDB 00H,29H,2CH,00H,31H,34H,37H,00HDB 3EH,41H,00H,49H,00H,52H,57H,00HDB 62H;==============================;===========延时参数表===========;==============================DELAY_T:DS 1DHDB 7EH,77H,00HDB 6AH,00H,5EH,00H,54H,4FH,00H,46HDB 00H,3FH,3BH,00H,35H,32H,2FH,00HDB 2AH,27H,00H,23H,00H,1FH,1DH,0C0HDB 1AH;==============================;============歌曲表=============;==============================TABLE:DW 2504H,2704H,2904H,2504HDW 2504H,2704H,2904H,2504HDW 2904H,2A04H,2C08HDW 2904H,2A04H,2C08HDW 2C02H,2E02H,2C02H,2A02H,2904H,2504HDW 2C02H,2E02H,2C02H,2A02H,2904H,2504HDW 2904H,2004H,2508HDW 2904H,2004H,2508HDW 0000HEND童鞋们可能发现了�数据表TABLE里面的数据才是歌曲数据。
单片机驱动蜂鸣器唱国歌的设计与原理
蜂鸣器演奏国歌(11机自创新1班王丽红1110100736)1设计任务本设计是以AT89C51芯片的电路为基础,外部加上三级管驱动蜂鸣器,以此来实现音乐演奏控制的硬件电路,通过软件程序来控制单片机内部的定时器使其演奏出优美动听的音乐。
按照要求选择音乐,在本次设计中以演奏《国歌》为例,将其转化为机器码存入单片机的存储器中。
2设计原理蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈产生磁场来驱动振动膜发声的,因此驱动需要一定的电流,单片机引脚输出的电流较小,基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路。
三极管的发射极E接电源,集电极C接蜂鸣器正极,蜂鸣器负极接地,三极管的基级B经过限流电阻R后由单片机引脚控制。
当输出高电平时,三极管T1截止,没有电流流过线圈,蜂鸣器不发声;当输出低电平时,三极管导通,这样蜂鸣器的电流形成回路,发出声音。
程序中改变单片引脚输出波形的频率,就可以调整控制蜂鸣器音调,产生各种不同音色、音调的声音。
另外,改变输出电平的高低电平占空比,则可以控制蜂鸣器的声音大小,这些我们都可以通过编程实验来验证。
3 软件设计3.1音调、节拍以及编码的确定一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能像电子琴那样能奏出多种音色的声音。
因此单片机奏乐只需弄清楚两个概念即可,也就是“音调”和节拍表示一个音符唱多长的时间。
3.1.1音调的确定不同音高的乐音是用C、D、E、F、G、A、B来表示,这7个字母就是音乐的音名,它们一般依次唱成DO、RE、MI、FA、SO、LA、SI,即唱成简谱的1、2、3、4、5、6、7,这是唱曲时乐音的发音,所以叫“音调”。
把C、D、E、F、G、A、B这一组音的距离分成12个等份,每一个等份叫一个“半音”。
两个音之间的距离有两个“半音”,就叫“全音”。
1) 要产生音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。
定时器实验(单片机控制蜂鸣器播放曲子——最炫民族风)
#include <REGX51.H>unsigned char h, l, time;sbit beep = P3^7;code unsigned char high[] = {0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音12345670xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, //1,2,3,4,5,6,7,0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音i2345670xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音1234567code unsigned char low[] = {0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音12345670x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, //1,2,3,4,5,6,7,0x8F, 0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音i2345670x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音1234567code unsigned char music[] ={6,1,2, 6,1,1, 5,1,1, 6,1,2, 6,1,1, 1,2,1, 1,2,2, 2,2,1, 1,2,1, 6,1,4, 1,2,2, 1,2,1, 5,1,1, 1,2,1,2,2,1, 3,2,1, 5,2,1, 5,2,1, 3,2,1, 2,2,2, 3,2,4, 6,2,1, 6,2,1, 6,2,1, 5,2,1, 3,2,1, 3,2,2, 1,2,1, 6,1,1,6,1,1, 6,1,1, 3,2,1, 2,2,4, 3,2,1, 3,2,1, 5,2,1, 3,2,1, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1, 5,1,1, 6,1,4,3,2,1, 3,2,1, 5,2,1, 3,2,1, 3,2,1, 5,2,1, 5,2,1, 6,2,1, 1,3,1, 6,2,1, 5,2,2, 6,2,4, 6,1,2, 6,1,1, 5,1,1,6,1,2, 1,2,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 2,2,1, 3,2,4, 6,1,1, 6,2,1, 6,2,1, 5,2,1, 2,2,1, 3,2,1, 2,2,1, 0,0,0,};void nint() interrupt 1 //T0中断程序,控制发音的音调{TR0 = 0; //先关闭T0beep =~beep; //输出方波, 发音TH0 = h; //下次的中断时间, 这个时间, 控制音调高低TL0 = l;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 < 4000; t2++); //延时期间, 可进入T0中断去发音TR0 = 0; //关闭T0, 停止发音}void song() //演奏一个音符{TH0 = h; //控制音调TL0 = l;TR0 = 1; //启动T0, 由T0输出方波去发音beep =~beep;delay(time); //控制时间长度}void main() //j表示第n+1首曲{ unsigned char k, i;i = 0;TMOD = 1; //置T0定时工作方式1ET0 = 1; //开T0中断EA = 1;time = 1;while(time) {k = music[i] + 7 * music[i + 1] - 1;//第i个是音符, 第i+1个是第几个八度h = high[k]; //从数据表中读出频率数值l = low[k]; //实际上, 是定时的时间长度time = music[i + 2]; //读出时间长度数值i += 3;song(); //发出一个音符}}。