51单片机嵌入式开发:15、STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒

STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒

  • 1 概述
  • 2 蜂鸣器操作方法
  • 3 蜂鸣器发出音声
  • 4 硬件电路
  • 5 软件实现
  • 6 整体工程:
  • 7 总结


在这里插入图片描述

1 概述

要实现一个基于STC89C52RC单片机的音乐盒,可以按照以下步骤进行:
(1)硬件连接:
将蜂鸣器连接到STC89C52RC单片机的一个IO口上(例如P1.0)。
连接其他必要的硬件,如按键、LCD显示屏等,以实现音乐盒的控制和用户交互功能。
(2)音乐文件准备:
将音乐文件转换为适合播放的格式,例如将音乐转换为一系列音符和节拍的组合。
将转换后的音乐数据保存在单片机的程序或外部存储器中(如EEPROM或Flash存储器)。
(3)编写程序:
使用C语言编写程序来控制STC89C52RC单片机的功能。
初始化必要的硬件接口,如IO口和定时器等。
编写播放音乐的函数,根据音乐数据控制蜂鸣器发声。
编写与用户交互的代码,如按键控制、显示当前播放状态等。
考虑使用定时器来控制音乐的节奏和节拍。
(4)主循环:
在主循环中实现音乐盒的逻辑控制。
监测用户的输入,根据输入进行相应的操作,如播放、暂停、停止、切换曲目等。
调用相应的函数来控制蜂鸣器发声和更新LCD显示。
(5)调试和优化:
进行测试和调试,确保音乐盒的各项功能正常工作。
根据需要进行性能优化,如减小程序体积、优化音乐数据存储等。
请注意,以上步骤只是一个概述,并不包含具体的代码实现。实际开发中需要根据具体需求和硬件环境进行详细的设计和编码。
在具体实现过程中,可以借助STC89C52RC单片机的IO口控制蜂鸣器输出声音,并使用定时器来控制音乐的节奏和节拍。此外,还可以添加其他功能,如音量控制、曲目选择、循环播放等,以增强音乐盒的功能和用户体验。

2 蜂鸣器操作方法

在C51单片机中操作蜂鸣器的方法通常是通过控制相应的IO口输出高低电平信号来实现。以下是一种常见的方法:
首先,确定连接蜂鸣器的IO口,假设为P1.0。
然后,按照以下步骤进行操作:
设置IO口为输出模式:
P1 = P1 & 0xFE; // 将P1.0设置为输出
发出蜂鸣器声音:
P1 = P1 | 0x01; // 将P1.0置为高电平(蜂鸣器发声)
停止蜂鸣器声音:
P1 = P1 & 0xFE; // 将P1.0置为低电平(蜂鸣器停止发声)
根据具体的单片机型号和开发环境,上述代码可能需要适当修改。请确保已经正确设置了IO口的方向和状态,并且将蜂鸣器正确连接到相应的IO口。
另外,如果需要生成特定频率的声音,可以使用定时器来控制蜂鸣器的开关时间,从而实现不同频率的声音效果。这需要针对具体的单片机和定时器进行相应的配置和编程。
请注意,在使用蜂鸣器时,要特别注意电源和电流的要求,以防止对单片机和蜂鸣器造成损坏。确保根据蜂鸣器的规格和要求进行正确的电气连接和电流限制。
以上是一种简单的方法来操作蜂鸣器,具体的实现可能会因单片机型号、开发环境和需求而有所不同。

3 蜂鸣器发出音声

蜂鸣器通常通过控制电流或电压的变化来产生不同的声音效果。通过改变电流或电压的频率、持续时间和幅度,可以产生不同频率和音调的声音。
在嵌入式系统中,控制蜂鸣器发声通常通过单片机或其他电路来实现。通过控制相应的IO口输出高低电平信号或调节PWM(脉冲宽度调制)信号,可以控制蜂鸣器的开关和声音的频率,从而产生不同的音效。具体的控制方法可以根据蜂鸣器类型和使用的电路进行调整和实现。
(1)为了尽可能还原音乐,国际标准音高包含了多个音高,使用了哆唻咪发嗦来嘻(表中用1234567)的音符,并对应不同的频率。为了模拟这些音高,下表列出了9个频率对应的音高。

在这里插入图片描述

(2)接下来,我们可以在Excel表格中使用以下公式来快速计算各个音高对应的计数值:T = 65535 - (1 / (频率 * 2 * 1.0851)) + 1。下图显示了上述频率对应的计数值:

在这里插入图片描述

(3)到这一步,还需要将之前计算得到的十进制计数值转换为十六进制计数值,因为51单片机的定时器计数值由高位和低位两部分组成。为了实现这个转换,我们可以在Excel中使用函数=DEC2HEX(单元格)来将对应单元格的十进制计数值转换为十六进制计数值。下图显示了之前计算得到的十进制计数值对应的十六进制计数值:

在这里插入图片描述

4 硬件电路

根据原理图所示:
控制引脚需要跳线到J18的第七引脚,才能控制喇叭。

在这里插入图片描述

5 软件实现

(1)定时器
为了实现音乐的还原,我们使用定时器来还原音高,并使用延时函数来还原音长。设计采用定时器中断产生一定频率的方波信号,驱动无源蜂鸣器来还原音高。同时,延时函数用于控制该频率的维持时间,从而还原音长。通过这样的方式,我们可以实现简谱中一个音符的还原,将它们连贯起来就能还原整段音乐。
根据表格添加音高对应的定时器计数值常量至ROM(9个音高)

code unsigned char yingaoh[63]={
0x92,0xC8,0xE4,0xF2,0xF9,0xFC,0xFE,0xFF,0xFF, //音符1的9个音高
0x9E,0xCE,0xE7,0xF3,0xF9,0xFC,0xFE,0xFF,0xFF,	//音符2的9个音高
0xA8,0xD4,0xEA,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符3的9个音高
0xAD,0xD6,0xEB,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符4的9个音高
0XB6,0XDB,0XED,0XF6,0XFB,0XFD,0XFE,0XFF,0XFF, //音符5的9个音高
0XBE,0XDF,0XEF,0XF7,0XFB,0XFD,0XFE,0XFF,0XFF, //音符6的9个音高
0XC5,0XE2,0XF1,0XF8,0XFC,0XFE,0XFF,0XFF,0XFF, //音符7的9个音高
}; //7个音符的9个八度高位计数值
code unsigned char yingaol[63]={
0x3C,0xF3,0x79,0x3C,0x1E,0x8F,0x47,0x23,0x91, //音符1的9个音高
0x2A,0xF3,0x79,0xBC,0xDE,0xEF,0x77,0x3B,0x9D,	//音符2的9个音高
0x9D,0x4E,0x27,0x13,0x89,0x45,0xA2,0x51,0xA8, //音符3的9个音高
0x6D,0xCE,0x61,0xB0,0xD8,0x6C,0xB6,0x5B,0xAD, //音符4的9个音高
0X86,0X43,0XA1,0XD0,0X68,0XB4,0XDA,0X6D,0XB6, //音符5的9个音高
0X8A,0X45,0XA2,0XD1,0XE8,0XF4,0XFA,0X7D,0XBE, //音符6的9个音高
0XBE,0XD3,0X6C,0XB5,0X5A,0X2D,0X16,0X8B,0XC5,	//音符7的9个音高
}; 7个音符的9个八度低位计数值 

(2)添加音乐对应的单片机代码(爱拼才会赢)
其中,music[0]代表节拍数,music[1]代表每分钟的节拍数。数组的结尾放入0表示音乐的结束。数组中的其他值按顺序每两个值表示一个音高和维持的时间(需要通过换算计算出实际时间)。。

code unsigned char music[]={
4,89,
5,4,2,5,4,1,6,4,1,
1,5,6,6,4,2,5,4,2,
6,4,1,1,5,1,6,4,2,
5,4,2,3,4,12,3,4,2,
3,4,1,5,4,1,6,4,6,
1,5,2,5,4,2,3,5,2,
3,5,1,2,5,1,1,5,2,
2,5,12,1,5,2,2,5,2,
3,5,2,3,5,2,2,5,2,
3,5,1,2,5,1,1,5,6,
6,4,1,1,5,1,2,5,2,
2,5,2,2,5,1,1,5,1,
6,4,2,5,4,8,6,4,2,
5,4,1,6,4,1,5,4,2,
1,5,2,6,4,2,5,4,2,
3,4,2,1,4,4,2,4,12,
1,4,2,2,4,2,3,4,6,
5,4,2,5,4,2,3,4,2,
1,5,2,7,4,2,6,4,6,
6,4,2,6,4,4,1,5,2,
2,5,1,3,5,1,5,5,4,
3,5,4,2,5,2,1,5,2,
5,4,2,1,5,2,2,5,1,
3,5,1,2,5,12,3,5,1,
2,5,1,1,5,4,2,5,1,
1,5,1,6,4,4,1,5,2,
3,4,1,1,5,1,1,5,2,
6,4,2,1,5,4,6,4,1,
5,4,1,3,4,2,5,4,16,
5,4,2,6,4,2,1,5,2,
6,4,2,6,4,8,3,5,2,
3,5,2,3,5,2,3,5,1,
2,5,1,2,5,6,2,5,1,
1,5,1,6,4,6,3,5,2,
2,5,4,1,5,1,2,5,1,
1,5,1,6,4,1,1,5,16,
5,4,2,6,4,2,1,5,6,
6,4,2,5,4,2,6,4,1,
1,5,1,6,4,2,5,4,2,
3,4,12,3,4,2,3,4,1,
5,4,1,6,4,6,1,5,2,
5,4,2,3,5,2,3,5,1,
2,5,1,1,5,2,2,5,12,
1,5,2,2,5,2,3,5,2,
3,5,2,2,5,2,3,5,1,
2,5,1,1,5,6,6,4,1,
1,5,1,2,5,2,2,5,2,
2,5,1,1,5,1,6,4,2,
5,4,8,6,4,2,5,4,1,
6,4,1,5,4,2,1,5,2,
6,4,2,5,4,2,3,4,2,
1,4,4,2,4,12,1,4,2,
2,4,2,3,4,6,5,4,2,
5,4,2,3,4,2,1,5,2,
7,4,2,6,4,6,6,4,2,
6,4,4,1,5,2,2,5,1,
3,5,1,5,5,2,3,5,4,
2,5,2,1,5,2,5,4,2,
1,5,2,2,5,1,3,5,1,
2,5,12,3,5,1,2,5,1,
1,5,4,2,5,1,1,5,1,
6,4,4,1,5,2,3,4,1,
1,5,1,1,5,2,6,4,2,
1,5,4,6,4,1,5,4,1,
3,4,2,5,4,16,5,4,2,
6,4,2,1,5,2,6,4,2,
6,4,8,3,5,2,3,5,2,
3,5,2,3,5,1,2,5,1,
2,5,6,2,5,1,1,5,1,
6,4,6,3,5,2,2,5,4,
1,5,1,2,5,1,1,5,1,
6,4,1,1,5,16,1,4,2,
2,4,2,3,4,6,5,4,2,
5,4,2,3,4,2,1,5,2,
7,4,2,6,4,6,6,4,2,
6,4,4,1,5,2,2,5,1,
3,5,1,5,5,4,3,5,4,
2,5,2,1,5,2,5,4,2,
1,5,2,2,5,1,3,5,1,
2,5,12,3,5,1,2,5,1,
1,5,4,2,5,1,1,5,1,
6,4,4,1,5,2,3,4,1,
1,5,1,1,5,2,6,4,2,
1,5,4,6,4,1,5,4,1,
3,4,2,5,4,16,5,4,2,
6,4,2,1,5,2,6,4,2,
6,4,8,3,5,2,3,5,2,
3,5,2,3,5,1,2,5,1,
2,5,6,2,5,1,1,5,1,
6,4,6,3,5,2,2,5,4,
1,5,1,2,5,1,1,5,1,
6,4,1,1,5,16,0};

(3)实现音高的控制程序

//使用定时器方式,实现发音的频率来实现音高
void sys_music_init(void)
{TMOD=0x01;		//置T0定时器工作在方式1EA=1;			//开总中断ET0=1;			//开定时器0中断,这两句等效于IE=0x82TR0=1; 				//开定时器0
}//音高模拟函数实际上就是利用定时器中断产生一定频率方波驱动蜂鸣器发出一定频率的声音。void music_t0_isr() interrupt 1 //定时器0中断函数
{TR0=0;		 //关闭定时器TR0BEEP=!BEEP;	 //蜂鸣状态取反TH0=timeh;	 //把timeh赋给定时0高位计数值TL0=timel;	 //把timel赋给定时0低位计数值TR0=1;	   //开定时器TR0
}
void music_delay(unsigned int t)  //节拍延时函数
{//根据每分钟节拍数,求解四分之一音符保持时长,四舍五入单位为10ms unsigned int time;unsigned int time_tmp = 0;//1000*((60/M1)) *t/M0time_tmp = (unsigned int)music[1]*(unsigned int)music[0];//time=15000UL*t/time_tmp; //根据节拍算出10ms的计数次数 time = 80*t;delay_ms(time);//TR0=0;
}void sys_music_test(void)
{unsigned char m,n;m=(music[buf_i]-1)*9+music[buf_i+1]; 	//获取音符对应计数值所在下标n=music[buf_i+2]; 						//获取音符保持时长值timeh=yingaoh[m]; 						//获取音符对应定时器计数值高位timel=yingaol[m]; 						//获取音符对应定时器计数值低位TH0=timeh;	//把timeh赋给定时0高位计数值TL0=timel;	//把timel赋给定时0低位计数值//TR0=1; 				//开定时器0music_delay(n); 	//执行音符保持函数buf_i=buf_i+3;	  	//读下一个音符if(music[buf_i]==0) {buf_i=2;	   	//如果到末尾则回到开头,循环播放}
}

6 整体工程:

在这里插入图片描述

//main.c文件

#include "includes.h"/******************************************************************/
/*                    微秒延时函数  //10us                         */
/******************************************************************/
void delay_us(unsigned int us)//delay us
{while(us--){}
}/******************************************************************/
/*                    微秒延时函数                                */
/******************************************************************/
void delay_ms(unsigned int Ms)//delay us
{while(Ms--){delay_us(100);}
}/*------------------------------------------------延时子程序
------------------------------------------------*/
void delay(unsigned int cnt) 
{while(--cnt);
}/*------------------------------------------------主函数
------------------------------------------------*/
void main (void)
{	sys_music_init();delay(10);delay_ms(1);sys_keynum_ledon(1,0);buf_i = 2;while(1){sys_music_test();}
}

//includes.h文件

#ifndef __INCLUDES_H__
#define __INCLUDES_H__//#include<reg52.h> #include<intrins.h> //汇编指令_nop_
#include<stdio.h> 	//标准输入输出//_nop_(); 产生一条NOP指令
//作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
//NOP指令为单周期指令,可由晶振频率算出延时时间。//8051 为每个机器周期 12 时钟
//对于12M晶振,延时1uS。
//11.0592M晶振,延时1.0851uS。//对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "STC89C5xRC_RDP.h"//应用层头文件
//#include "c51_gpio.h"
#include "c51_ledtube.h"
//#include "c51_key.h"
//#include "c51_timer.h"
//#include "c51_exit.h"
//#include "c51_lcd1602.h"
//#include "c51_iic.h"
//#include "c51_tx1838.h"
//#include "c51_uart.h"
#include "c51_music.h"extern void delay(unsigned int cnt);
extern void delay_us(unsigned int us);//delay us;
extern void delay_ms(unsigned int Ms);//delay Ms;#endif

//c51_ledtube.c文件

#include "includes.h"// 显示段码值01234567,可对应原理图查看显示不同图形对应的引脚高点电平配置状态
unsigned char const EL[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,\0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F///********************************************************
//函数名称:sys_ledtube_on1
//函数功能:点亮一个数码管全为亮起来
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//void sys_ledtube_on1(void)
//{
//	//根据原理图,将P0口全部输出高电平,P2选择0号数码管
//	P0=0xFF;//取显示数据,段码
//	P2=0;  	//取位码
//}///********************************************************
//函数名称:sys_ledtube_on2
//函数功能:显示一组数据
//入口参数:
//出口参数:
//修    改:
//内    容:
//********************************************************/
//static unsigned char ledtube_cnt = 0;
//void sys_ledtube_on2(void)
//{
//	ledtube_cnt++;
//	if(ledtube_cnt>7)
//	{
//		ledtube_cnt = 0;
//	}
//	P0 = 0x00;				//防止切换数码管瞬间有虚影出现
//	P2 = 0x00;
//	P0 = EL[ledtube_cnt];	//取显示数据,段码
//	P2 = ledtube_cnt;  		//取位码
//	
//	//根据人眼适应虚影缓冲时间为50ms左右
//	//我们调整delay在500以下可以看到明显的看起来是一串数据一起显示
//	delay(100); 			
//}/********************************************************
函数名称:sys_keynum_ledon
函数功能:显示按键数值
入口参数:按键数值
出口参数:
修    改:
内    容:
********************************************************/
void sys_keynum_ledon(unsigned char num,unsigned char pn)
{//根据原理图,将P0口全部输出高电平,P2选择0号数码管P0 = 0x00;		//防止切换数码管瞬间有虚影出现P2 = pn;  		//取位码P0 = EL[num];	//取显示数据,段码
}

//c51_music.c 文件

#include "includes.h"unsigned char timeh=0;
unsigned char timel=0;//TR0计数器高位值、低位值
unsigned int buf_i = 2;code unsigned char yingaoh[63]={
0x92,0xC8,0xE4,0xF2,0xF9,0xFC,0xFE,0xFF,0xFF, //音符1的9个音高
0x9E,0xCE,0xE7,0xF3,0xF9,0xFC,0xFE,0xFF,0xFF,	//音符2的9个音高
0xA8,0xD4,0xEA,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符3的9个音高
0xAD,0xD6,0xEB,0xF5,0xFA,0xFD,0xFE,0xFF,0xFF, //音符4的9个音高
0XB6,0XDB,0XED,0XF6,0XFB,0XFD,0XFE,0XFF,0XFF, //音符5的9个音高
0XBE,0XDF,0XEF,0XF7,0XFB,0XFD,0XFE,0XFF,0XFF, //音符6的9个音高
0XC5,0XE2,0XF1,0XF8,0XFC,0XFE,0XFF,0XFF,0XFF, //音符7的9个音高
}; //7个音符的9个八度高位计数值code unsigned char yingaol[63]={
0x3C,0xF3,0x79,0x3C,0x1E,0x8F,0x47,0x23,0x91, //音符1的9个音高
0x2A,0xF3,0x79,0xBC,0xDE,0xEF,0x77,0x3B,0x9D,	//音符2的9个音高
0x9D,0x4E,0x27,0x13,0x89,0x45,0xA2,0x51,0xA8, //音符3的9个音高
0x6D,0xCE,0x61,0xB0,0xD8,0x6C,0xB6,0x5B,0xAD, //音符4的9个音高
0X86,0X43,0XA1,0XD0,0X68,0XB4,0XDA,0X6D,0XB6, //音符5的9个音高
0X8A,0X45,0XA2,0XD1,0XE8,0XF4,0XFA,0X7D,0XBE, //音符6的9个音高
0XBE,0XD3,0X6C,0XB5,0X5A,0X2D,0X16,0X8B,0XC5,	//音符7的9个音高
}; //7个音符的9个八度低位计数值 code unsigned char music[]={
4,89,
5,4,2,5,4,1,6,4,1,
1,5,6,6,4,2,5,4,2,
6,4,1,1,5,1,6,4,2,
5,4,2,3,4,12,3,4,2,
3,4,1,5,4,1,6,4,6,
1,5,2,5,4,2,3,5,2,
3,5,1,2,5,1,1,5,2,
2,5,12,1,5,2,2,5,2,
3,5,2,3,5,2,2,5,2,
3,5,1,2,5,1,1,5,6,
6,4,1,1,5,1,2,5,2,
2,5,2,2,5,1,1,5,1,
6,4,2,5,4,8,6,4,2,
5,4,1,6,4,1,5,4,2,
1,5,2,6,4,2,5,4,2,
3,4,2,1,4,4,2,4,12,
1,4,2,2,4,2,3,4,6,
5,4,2,5,4,2,3,4,2,
1,5,2,7,4,2,6,4,6,
6,4,2,6,4,4,1,5,2,
2,5,1,3,5,1,5,5,4,
3,5,4,2,5,2,1,5,2,
5,4,2,1,5,2,2,5,1,
3,5,1,2,5,12,3,5,1,
2,5,1,1,5,4,2,5,1,
1,5,1,6,4,4,1,5,2,
3,4,1,1,5,1,1,5,2,
6,4,2,1,5,4,6,4,1,
5,4,1,3,4,2,5,4,16,
5,4,2,6,4,2,1,5,2,
6,4,2,6,4,8,3,5,2,
3,5,2,3,5,2,3,5,1,
2,5,1,2,5,6,2,5,1,
1,5,1,6,4,6,3,5,2,
2,5,4,1,5,1,2,5,1,
1,5,1,6,4,1,1,5,16,
5,4,2,6,4,2,1,5,6,
6,4,2,5,4,2,6,4,1,
1,5,1,6,4,2,5,4,2,
3,4,12,3,4,2,3,4,1,
5,4,1,6,4,6,1,5,2,
5,4,2,3,5,2,3,5,1,
2,5,1,1,5,2,2,5,12,
1,5,2,2,5,2,3,5,2,
3,5,2,2,5,2,3,5,1,
2,5,1,1,5,6,6,4,1,
1,5,1,2,5,2,2,5,2,
2,5,1,1,5,1,6,4,2,
5,4,8,6,4,2,5,4,1,
6,4,1,5,4,2,1,5,2,
6,4,2,5,4,2,3,4,2,
1,4,4,2,4,12,1,4,2,
2,4,2,3,4,6,5,4,2,
5,4,2,3,4,2,1,5,2,
7,4,2,6,4,6,6,4,2,
6,4,4,1,5,2,2,5,1,
3,5,1,5,5,2,3,5,4,
2,5,2,1,5,2,5,4,2,
1,5,2,2,5,1,3,5,1,
2,5,12,3,5,1,2,5,1,
1,5,4,2,5,1,1,5,1,
6,4,4,1,5,2,3,4,1,
1,5,1,1,5,2,6,4,2,
1,5,4,6,4,1,5,4,1,
3,4,2,5,4,16,5,4,2,
6,4,2,1,5,2,6,4,2,
6,4,8,3,5,2,3,5,2,
3,5,2,3,5,1,2,5,1,
2,5,6,2,5,1,1,5,1,
6,4,6,3,5,2,2,5,4,
1,5,1,2,5,1,1,5,1,
6,4,1,1,5,16,1,4,2,
2,4,2,3,4,6,5,4,2,
5,4,2,3,4,2,1,5,2,
7,4,2,6,4,6,6,4,2,
6,4,4,1,5,2,2,5,1,
3,5,1,5,5,4,3,5,4,
2,5,2,1,5,2,5,4,2,
1,5,2,2,5,1,3,5,1,
2,5,12,3,5,1,2,5,1,
1,5,4,2,5,1,1,5,1,
6,4,4,1,5,2,3,4,1,
1,5,1,1,5,2,6,4,2,
1,5,4,6,4,1,5,4,1,
3,4,2,5,4,16,5,4,2,
6,4,2,1,5,2,6,4,2,
6,4,8,3,5,2,3,5,2,
3,5,2,3,5,1,2,5,1,
2,5,6,2,5,1,1,5,1,
6,4,6,3,5,2,2,5,4,
1,5,1,2,5,1,1,5,1,
6,4,1,1,5,16,0};//使用定时器方式,实现发音的频率来实现音高
void sys_music_init(void)
{TMOD=0x01;		//置T0定时器工作在方式1EA=1;			//开总中断ET0=1;			//开定时器0中断,这两句等效于IE=0x82TR0=1; 				//开定时器0
}//音高模拟函数实际上就是利用定时器中断产生一定频率方波驱动蜂鸣器发出一定频率的声音。void music_t0_isr() interrupt 1 //定时器0中断函数
{TR0=0;		 //关闭定时器TR0BEEP=!BEEP;	 //蜂鸣状态取反TH0=timeh;	 //把timeh赋给定时0高位计数值TL0=timel;	 //把timel赋给定时0低位计数值TR0=1;	   //开定时器TR0
}void music_delay(unsigned int t)  //节拍延时函数
{//根据每分钟节拍数,求解四分之一音符保持时长,四舍五入单位为10ms unsigned int time;unsigned int time_tmp = 0;//1000*((60/M1)) *t/M0time_tmp = (unsigned int)music[1]*(unsigned int)music[0];//time=15000UL*t/time_tmp; //根据节拍算出10ms的计数次数 time = 168*t;delay_ms(time);//TR0=0;
}void sys_music_test(void)
{unsigned char m,n;m=(music[buf_i]-1)*9+music[buf_i+1]; 	//获取音符对应计数值所在下标n=music[buf_i+2]; 						//获取音符保持时长值timeh=yingaoh[m]; 						//获取音符对应定时器计数值高位timel=yingaol[m]; 						//获取音符对应定时器计数值低位TH0=timeh;	//把timeh赋给定时0高位计数值TL0=timel;	//把timel赋给定时0低位计数值//TR0=1; 				//开定时器0music_delay(n); 	//执行音符保持函数buf_i=buf_i+3;	  	//读下一个音符if(music[buf_i]==0) {buf_i=2;	   	//如果到末尾则回到开头,循环播放}
}

//c51_music.h文件

#ifndef __C51_MUSIC_H__
#define __C51_MUSIC_H__#define BEEP	P12extern unsigned char timeh;
extern unsigned char timel;//TR0计数器高位值、低位值extern unsigned int buf_i;extern void sys_music_init(void);
extern void music_t0_isr();
extern void music_delay(unsigned int t);  //节拍延时函数
extern void sys_music_test(void);#endif

//c51_ledtube.h文件

#ifndef __C51_LEDTUBE_H__
#define __C51_LEDTUBE_H__extern unsigned char const EL[];//extern void sys_ledtube_on1(void);
//extern void sys_ledtube_on2(void);extern void sys_keynum_ledon(unsigned char num,unsigned char pn);#endif

7 总结

蜂鸣器操作的一般总结:
(1)硬件连接:
将蜂鸣器连接到单片机的一个IO口上,通常使用GPIO口。
(2)初始化:
在程序开始时,需要对相关IO口进行初始化,将其配置为输出模式。
(3)发出声音:
要使蜂鸣器发出声音,将相应的IO口置高电平(或低电平,具体根据电路设计而定)即可。
通过控制IO口的电平状态,可以控制蜂鸣器的开关状态。
(4)延时:
要控制蜂鸣器发声的时间长度,可以使用延时函数。
在C51中,常用的延时函数包括delay、_nop_等,它们可以提供一定的延时效果。
(5)控制频率和音调:
要实现不同的频率和音调,可以使用定时器功能。
在C51中,可以通过配置定时器相关寄存器,设置定时器的工作方式、计数值和预分频等,从而控制定时器的频率和周期。
通过定时器中断,可以实现产生一定频率的方波信号,驱动蜂鸣器发声。
(6)停止声音:
要停止蜂鸣器的声音,将相应的IO口置低电平(或高电平)即可。
需要注意的是,具体的蜂鸣器操作步骤和代码实现可能会根据使用的单片机型号和编程环境而有所差异。在编写程序时,可以参考相关的单片机手册和编程指南,以及使用的开发工具提供的文档和示例代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32项目分享:智能宠物喂食系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.com/video/BV1zy411z7…

关于对CSDN的谴责

关于对CSDN的谴责 如果不是心血来潮登了一次旧帐号我是万万不会想到&#xff0c;所有的文章都被设置成了仅VIP可见。 CSDN你的VIP有多不受人待见您不知道吗&#xff1f;为什么要把我用于你开通VIP刷绩效的工具&#xff1f; 这种东西不应该首先经过同意再开启吗&#xff1f;默认…

JavaWeb day01-HTML入门

Web前端 课程安排 HTML、CSS简介 HTML快速入门 实现标题排版 新闻标题样式

深度学习程序环境配置

深度学习环境配置 因为之前轻薄本没有显卡跑不起来&#xff0c;所以换了台电脑重新跑程序&#xff0c;故记录一下配置环境的步骤及常见错误 本人数学系&#xff0c;计算机部分知识比较匮乏&#xff0c;计算机专业同学可以略过部分内容 深度学习环境配置 深度学习环境配置 CUD…

MATLAB算法实战应用案例精讲-【数模应用】多元方差分析MANOVA(附MATLAB、python和R语言代码实现)

目录 知识储备 方差分析 一、单因素方差分析 二、双因素方差分析 三、多因素方差分析 四、事后多重比较 五、重复测量方差 六、协方差分析 七、多元方差分析 算法原理 多元方差分析的特点 多元方差分析的使用条件 应用案例 代码实现 MATLAB python R语言 知…

StringBuilder, Stringbuffer,StringJoiner

StringBuilder StringBuilder 代表可变字符串对象&#xff0c;相当于是一个容器&#xff0c;里面装的字符串是可以改变的&#xff0c;就是用来操作字符串的。 StringBuilder 比String更适合做字符串的修改操作&#xff0c;效率更高&#xff0c;代码更加的简洁。 public clas…

在结束的地方重新开始:十指之梢与新的轮回

一、前述 如果你想感受人潮汹涌&#xff0c;那么就请到大城市繁华街区的十字路口去看一看&#xff0c;尤其是节假日。 所以&#xff0c;交警对于城市交通的通畅&#xff0c;人们出行顺利的保障&#xff0c;是异常重要的。 交警&#xff0c;指挥交通有很多工具和方法&#xff0…

vscode 文件颜色变绿色

解决&#xff1a;关闭git功能 在设置中搜索Git:Enabled&#xff0c;取消Decorations: Enabled的勾选

04-用户画像+sqoop使用

优点 sqoop的作用是实现数据的导入和导出&#xff0c;主要是对数据库和数据仓库之间的操作 只要是支持jdbc连接的数据库都可以使用sqoop操作 添加Sqoop到环境变量中 export SQOOP_HOME/export/server/sqoop export PATH$PATH:$SQOOP_HOME/bin:$SQOOP_HOME/sbinsource /etc/…

嵌入式单片机软件与硬件的结合方法分析

不知道大家有没有疑惑,为什么软件能控制硬件?关于这个问题,给出直观解释的文章:本文分析STM32单片机到底是如何软硬件结合的,分析单片机程序如何编译,运行。 软硬件结合 初学者,通常有一个困惑,就是为什么软件能控制硬件?就像当年的51,为什么只要写P1=0X55,就可以…

Leetcode3212. 统计 X 和 Y 频数相等的子矩阵数量

Every day a Leetcode 题目来源&#xff1a;3212. 统计 X 和 Y 频数相等的子矩阵数量 解法1&#xff1a;二维前缀和 维护二维前缀和&#xff0c;分别统计 ‘X’ 和 ‘Y’ 的个数。 统计足以下条件的子矩阵数量&#xff1a; 包含 grid[0][0]‘X’ 和 ‘Y’ 的频数相等。至少…

贪吃蛇超精讲(C语言)

前言 如果你还是个萌新小白&#xff0c;那么该项目的攻克过程一定会十分艰难。虽然作者已经将文章尽可能写的逻辑清晰&#xff0c;内容详细。但所谓“纸上得来终觉浅”&#xff0c;在讲到陌生结构和函数时&#xff0c;大家请一定自己动手去敲一遍代码&#xff0c;这很重要&…

00 JavaWeb

学习资料&#xff1a;B站视频-黑马程序员JavaWeb基础教程 文章目录 JavaWeb1、JavaWeb简介2、 JavaWeb主要内容3、JavaWeb技术栈4、JavaWeb课程安排5、Web核心课程安排 JavaWeb 1、JavaWeb简介 Web&#xff1a;全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏…

Mysql-索引结构

一.什么是索引&#xff1f; 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引 二.无索引的情况 找到…

C++ | Leetcode C++题解之第273题整数转换英文表示

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<string> singles {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Ni…

DC-1靶场打靶第一次!!!!冲冲冲!

今天打了一下DC-1这个靶场&#xff0c;感觉收获比大&#xff0c;我就来记录一下。 我的思路是下面的这个 我们先把靶机导入&#xff0c;然后与我们的liunx(攻击机)在同一个网段中&#xff0c;这也大大的减低难度。 然后我们先对自己这个网段内存活的主机进行操作&#xff0c;我…

【Spring Boot】网页五子棋项目中遇到的困难及解决方法

目录 一、HikariPool-1 - Starting异常二、Invalid bound statement (not found)异常三、The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary异常四、The server time zone value时区报错异常五、补充知识点…

免费【2024】springboot 白优校园社团网站的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

Django transaction.atomic()事务处理

在Django中&#xff0c;transaction.atomic()是一个上下文管理器&#xff0c;它会自动开始一个事务&#xff0c;并在代码块执行完毕后提交事务。如果在代码块中抛出异常&#xff0c;事务将被自动回滚&#xff0c;确保数据库的一致性和完整性。 在实际应用中&#xff0c;你可能需…

[HTML]一文掌握

背景知识 主流浏览器 浏览器是展示和运行网页的平台&#xff0c; 常见的五大浏览器有 IE浏览器、火狐浏览器&#xff08;Firefox&#xff09;、谷歌浏览器&#xff08;Chrome&#xff09;、Safari浏览器、欧朋浏览器&#xff08;Opera&#xff09; 渲染引擎 浏览器解析代码渲…