51单片机学习--蜂鸣器播放音乐

在这里插入图片描述
在这里插入图片描述
由原理图可知,蜂鸣器BEEP与P1_5 相关,但其实这个原理图有错,实测接的是P2_5
下面这个代码就是以500HZ的频率响500ms的例子

sbit Buzzer = P2^5;

unsigned char KeyNum;
unsigned int i;

void main()
{
	while(1)
	{
		KeyNum = Key();
		if(KeyNum)
		{
			for(i = 0; i < 500; i ++) {
				Buzzer = !Buzzer;
				Delay(1);// 1ms翻转一次,周期就是2ms,频率就是500HZ 
			} //一共会响500ms
			
		}
		
	}
}

接下来先把这个发出声响的代码封装成Buzzer模块,接下来的目标是实现发出不同音调的声响



在这里插入图片描述
先来看用定时器实现的蜂鸣器发生,每次中断就翻转一次Buzzer,中断每1ms执行一次,所以翻转周期是2ms,音调一样

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"


sbit Buzzer = P2^5;



void main()
{
	Timer0_Init();
	
	while(1)
	{
		
	}
}


void Timer0_Routine() interrupt 1
{
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	Buzzer = !Buzzer;
}

只要更改中断函数中的定时初值,翻转需要的的时长就会变化,从而改变声音的周期进而改变音调
在这里插入图片描述
比如中央C的重装载值是64580,这个声调对应的初值如下

void Timer0_Routine() interrupt 1
{
	TL0 = 64580 % 256;		//设置定时初值
	TH0 = 64580 / 256;		//设置定时初值
	Buzzer = !Buzzer;
}

接下来只要稍微费点力气,把所有重装载值整理到一个数组里,使数组的每个序号对应一个音调,需要的时候调用序号就行

unsigned int FreqTable[] = { //中央C以及高八度低八度的音调由低到高
	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
};

扒出小星星的简谱,把音调对应的数组序号存到一个Music数组里,按序遍历这个数组就能比较完整地播放一首小星星啦

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"


sbit Buzzer = P2^5;

unsigned int FreqTable[] = {
	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
};

unsigned char FreqSelect, MusicSelect;

unsigned char Music[] = {12,12,19,19,21,21,19,17,17,16,16,14,14,12};
//小星星简谱音调对应的数组下标(前两句)

void main()
{
	Timer0_Init();
	
	while(1)
	{
		FreqSelect = Music[MusicSelect];
		MusicSelect ++;
		Delay(500); //音符时长,可修改
		TR0 = 0; //定时器关闭,自然停顿,否则两个连音之间没有了间隔
		Delay(5);
		TR0 = 1; //定时器开启
	}
}


void Timer0_Routine() interrupt 1
{
	TL0 = FreqTable[FreqSelect] % 256;		//设置定时初值
	TH0 = FreqTable[FreqSelect] / 256;		//设置定时初值
	Buzzer = !Buzzer;
}


但这样还不完美,每个音符只能固定地响500ms,想要自主控制音符的时长,则又需要一个数组来记录每个音符的长度!十六分音符记为1,八分音符记为2,四分音符记为4。。。。。

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"


sbit Buzzer = P2^5;

unsigned int FreqTable[] = {
	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
};

unsigned char FreqSelect, MusicSelect;

unsigned char Music[] = {12,12,19,19,21,21,19,17,17,16,16,14,14,12};
//小星星简谱音调对应的数组下标(前两句)

unsigned char Music2[] ={4,4,4,4,4,4,8,4,4,4,4,4,4,8};
//每个音符的时长

void main()
{
	Timer0_Init();
	
	while(1)
	{
		FreqSelect = Music[MusicSelect];
		Delay(125 * Music2[MusicSelect]);
		MusicSelect ++;
		TR0 = 0; //定时器关闭,自然停顿,否则两个连音之间没有了间隔
		Delay(5);
		TR0 = 1; //定时器开启
	}
}


void Timer0_Routine() interrupt 1
{
	TL0 = FreqTable[FreqSelect] % 256;		//设置定时初值
	TH0 = FreqTable[FreqSelect] / 256;		//设置定时初值
	Buzzer = !Buzzer;
}


最后还有一点,歌曲中不是一直都有声音的,所以需要有休止符,不发声,在音调数组的最后加上一个0,这样Music数组中也能存休止符了,中断函数中特判一下,不为0时才发声
以下就是一个比较完整地蜂鸣器播放音乐的代码了!

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"


sbit Buzzer = P2^5;

unsigned int FreqTable[] = {
	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,
	0
}; //最后一个是休止符

unsigned char FreqSelect, MusicSelect;

unsigned char Music[] = {12,12,19,19,21,21,19,17,17,16,16,14,14,12};
//小星星简谱音调对应的数组下标(前两句)

unsigned char Music2[] ={4,4,4,4,4,4,8,4,4,4,4,4,4,8};
//每个音符的时长

void main()
{
	Timer0_Init();
	
	while(1)
	{
		FreqSelect = Music[MusicSelect];
		Delay(125 * Music2[MusicSelect]);
		MusicSelect ++;
		TR0 = 0; //定时器关闭,自然停顿,否则两个连音之间没有了间隔
		Delay(5);
		TR0 = 1; //定时器开启
	}
}


void Timer0_Routine() interrupt 1
{
	if(FreqTable[FreqSelect] != 0) //若不为休止符
	{
		TL0 = FreqTable[FreqSelect] % 256;		//设置定时初值
		TH0 = FreqTable[FreqSelect] / 256;		//设置定时初值
		Buzzer = !Buzzer;
	}
}

最后一个问题,当歌曲音符比较多变化复杂的时候,数据量巨大,数组存不下,那么就要用到之前的方法,在Music数组前加上关键字code ,把数据存到flash里面,同时使数据变成只可读取,不可更改

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊买家账号ip关联怎么处理

对于亚马逊买家账号&#xff0c;同样需要注意IP关联问题。在亚马逊的眼中&#xff0c;如果多个买家账号共享相同的IP地址&#xff0c;可能会被视为潜在的操纵、违规或滥用行为。这种情况可能导致账号受到限制或处罚。 处理亚马逊买家账号IP关联问题&#xff0c;建议采取以下步骤…

实用干货!一文读懂Salesforce中6种数据关系类型!

Salesforce中对象之间的数据关系可能是一个棘手的话题。对于创建自定义对象的业务场景&#xff0c;需要决定使用哪些关系类型来扩展Salesforce数据模型。 01 查找关系 查找关系&#xff08;Lookup Relationships&#xff09;是一种松散耦合&#xff08;loosely coupled&…

[React]生命周期

前言 学习React&#xff0c;生命周期很重要&#xff0c;我们了解完生命周期的各个组件&#xff0c;对写高性能组件会有很大的帮助. Ract生命周期 React 生命周期分为三种状态 1. 初始化 2.更新 3.销毁 初始化 1、getDefaultProps() 设置默认的props&#xff0c;也可以用duf…

【Quartus FPGA】EMIF DDR3 读写带宽测试

在通信原理中&#xff0c;通信系统的有效性用带宽来衡量&#xff0c;带宽定义为每秒传输的比特数&#xff0c;单位 b/s&#xff0c;或 bps。在 DDR3 接口的产品设计中&#xff0c;DDR3 读/写带宽是设计者必须考虑的指标。本文主要介绍了 Quartus FPGA 平台 EMIF 参数配置&#…

Tomcat 创建https

打开CMD,按下列输入 keytool -genkeypair -alias www.bo.org -keyalg RSA -keystore d:\ambition.keystore -storetype pkcs12 输入密钥库口令:123456 再次输入新口令:123456 您的名字与姓氏是什么? [Unknown]: www.ambition.com 您的组织单位名称是什么? [Unknown…

cc2652在使用过程中的一些注意事项

可能不只是cc2652有这些坑&#xff0c;估计cc26xx系列都存在。 CCS的预编译宏配置位置 时钟获取 时钟获取__STATIC_INLINE uint32_t SysCtrlClockGet( void )在sys_ctrl.h中&#xff0c;sys_ctrl.h没有在工程路径下面&#xff0c;在其sdk中 节拍时间获取 ICall_getTicks(); …

IPv6 over IPv4隧道配置举例

配置IPv6 over IPv4手动隧道示例 组网需求 如图1所示&#xff0c;两台IPv6主机分别通过SwitchA和SwitchC与IPv4骨干网络连接&#xff0c;客户希望两台IPv6主机能通过IPv4骨干网互通。 图1 配置IPv6 over IPv4手动隧道组网图 配置思路 配置IPv6 over IPv4手动隧道的思路如下&…

roop 视频换脸

roop: one click face swap. 只用一张人脸图片&#xff0c;就能完成视频换脸。 项目地址&#xff1a; https://github.com/s0md3v/roopColab 部署&#xff1a; https://github.com/dream80/roop_colab 本文是本地部署的实践记录。 环境基础 OS: Ubuntu 22.04.2 LTSKernel: 5…

Redis实战(4)——Redisson分布式锁

1 基于互斥命令实现分布式锁的弊端 根据上篇文章基于redis互斥命令实现的分布式锁任然存在一定的弊端 1无法重入: 同一个线程无法重新获得同一把锁2超时删除 &#xff1a;会因为超时、任务阻塞而自动释放锁&#xff0c;出现其他线程抢占锁出现并行导致线程不安全的问题3 不可…

unity行为决策树实战详解

一、行为决策树的概念 行为决策树是一种用于游戏AI的决策模型&#xff0c;它将游戏AI的行为分解为一系列的决策节点&#xff0c;并通过节点之间的连接关系来描述游戏AI的行为逻辑。在行为决策树中&#xff0c;每个节点都代表一个行为或决策&#xff0c;例如移动、攻击、逃跑等…

LInux的安装(VMware,网卡设置,SSH连接工具)

Linux的安装 1、安装方式介绍 1.安装方式: 物理机安装:直接将操作系统安装到服务器硬件上 虚拟机安装:通过虚拟机软件安装 **虚拟机( Virtual Machine&#xff09;**指通过软件模拟的具有完整硬件系统功能、运行在完全隔离环境中的完整计算机系统。 2、安装Linux 在官网将…

20款奔驰S350升级原厂HUD抬头显示系统,提升您的行车安全

HUD是平视显示器的简称&#xff0c;它原先是运用在航空器上的飞行辅助仪器。指飞行员不需要低头&#xff0c;就能够看到他需要的重要资讯。由于HUD的方便性以及能够提高飞行安全&#xff0c;这项技术后来也发展到汽车行业。汽车搭载的HUD抬头数字显示功能&#xff0c;是利用光学…

Toolformer :让AI学会使用工具

paper: 《Toolformer: Language Models Can Teach Themselves to Use Tools 》 核心思想&#xff0c; 1. Sampling API Calls &#xff1a;设计设计prompt,让模型生成含API调用的文本&#xff08;如图3&#xff09;&#xff0c;只保留K个概率最高的API调用 2. Executing API …

MySql006——基本的SELECT查询语句

在《MySql003——结构化查询语言SQL基础知识》中&#xff0c;我们学习了有关SQL的基础知识&#xff0c;也知道SQL中查询语句SELECT使用最为频繁 接下来我们将学习一些基本的SELECT查询语句 一、SELECT语句的通用语法 在MySQL数据库中&#xff0c;使用SELECT语句可以查询数据…

Android Studio多渠道打包

使用环境&#xff1a; Android studio 多渠道打包 使用方法&#xff1a; 1 APP下build.gradle文件 flavorDimensions "default"productFlavors {huawei {dimension "default"manifestPlaceholders [ channel:"huawei" ]}xiaomi {dimension &…

Nginx学习教程(基础篇)

目录 一、Nginx安装 二、Nginx基本使用 2.1、目录结构 conf html logs sbin 2.2、基本运行原理 2.3、nginx.conf最小配置解析 worker_processes worker_connections include mime.types default_type application/octet-stream sendfile on keepalive_timeout…

Python实现GA遗传算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

lc1074.元素和为目标值的子矩阵数量

创建二维前缀和数组 两个for循环&#xff0c;外循环表示子矩阵的左上角&#xff08;x1,y1&#xff09;&#xff0c;内循环表示子矩阵的右下角&#xff08;x2,y2&#xff09; 两个for循环遍历&#xff0c;计算子矩阵的元素总和 四个变量&#xff0c;暴力破解的时间复杂度为O(…

驱动开发(中断)

头文件&#xff1a; #ifndef __LED_H__ #define __LED_H__#define PHY_LED1_MODER 0X50006000 #define PHY_LED1_ODR 0X50006014 #define PHY_LED1_RCC 0X50000A28#define PHY_LED2_MODER 0X50007000 #define PHY_LED2_ODR 0X50007014 #define PHY_LED2_RCC 0X50000A28#def…

【安装Tomcat,web站点部署】

Tomcat部署 第一种安装 yum install tomcat.noarch -y yum install tomcat-webapps.noarch -y #启动脚本 [rootlocalhost ~]# systemctl start tomcat这时可以通过IP地址端口访问 第二种安装 点击此处找到apache-tomcat-8.5.70.tar.gz 官网下载JDK #先安装JDK [rootlocalh…