当前位置: 首页 > news >正文

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里面,同时使数据变成只可读取,不可更改

相关文章:

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

由原理图可知&#xff0c;蜂鸣器BEEP与P1_5 相关&#xff0c;但其实这个原理图有错&#xff0c;实测接的是P2_5 下面这个代码就是以500HZ的频率响500ms的例子 sbit Buzzer P2^5;unsigned char KeyNum; unsigned int i;void main() {while(1){KeyNum Key();if(KeyNum){for(i …...

【Vue组件eval方法的使用】

Vue页面中条件可以放在当前vue页面中而无需影响到组件 如 这是我的表格操作列按钮&#xff0c;需求是第四个按钮如果表格当前数据的is_execl字段为0则显示否则隐藏 这种条件判断很频繁 如果像之前一样给一个标识&#xff0c;页面多了就难以维护&#xff0c;而且判断条件如果不…...

C++ 多文件结构和编译预处理命令

1. C程序的一般组织结构 C源程序的结构基本上都是由3个部分构成&#xff1a;类的定义、类的成员的实现和主函数。因为所编写的程序比较小&#xff0c;所以这三个部分都写在了同一个文件当中。在规模比较大的项目中&#xff0c;往往需要多个源程序文件&#xff0c;每个源程序文…...

QT实现中英文键盘

使用Qt中实现中英文键盘&#xff0c;支持各种linux嵌入式设备。 实现思路&#xff1a;需要一个中文字体库&#xff0c;将字体库加载到一个Hash容器&#xff0c;字母和拼音作为key值&#xff0c;对应的中文作为value值。 核心代码&#xff1a; #include "UKeyBoard.h"…...

java中并发编程CompletableFuture和supplyAsync的用法

在Java中&#xff0c;并发编程可以使用CompletableFuture类来实现异步操作和并行任务。其中&#xff0c;supplyAsync是CompletableFuture类的一个静态方法&#xff0c;用于执行一个有返回值的异步任务。 supplyAsync方法的语法如下&#xff1a; public static <U> Comp…...

chrony服务器

目录 1.chrony简介 2.chrony安装配置 2.1 chrony安装及配置 非常重要&#xff1a;在配置之前&#xff0c;检查防火墙和selinux是否关闭 3.将chrony配置为其他主机的时间服务器 3.1 修改chrony配置文件 4.chronyc命令 1.chrony简介 chrony 是开源的遵循网络时间协议&…...

春秋云镜 CVE-2021-24762

春秋云镜 CVE-2021-24762 WordPress Plugin Perfect Survey 注入 靶标介绍 WordPress Perfect Survey plugin在1.5.2之前版本存在SQL注入漏洞&#xff0c;该漏洞源于基于数据库的应用缺少对外部输入SQL语句的验证。攻击者可利用该漏洞执行非法SQL命令。 启动场景 漏洞利用 …...

K8s中的Service

Service 1.Service存在的意义&#xff1f; &#xff08;1&#xff09;pod注册在service里面&#xff0c;做服务发现使用 &#xff08;2&#xff09;定义一组Pod访问策略&#xff08;负载均衡&#xff09; 2.Pod和Service关系 通过service实现Pod的负载均衡 3.常用Service类…...

[软件工程] 全局分析规格说明书模板

1 价值需求 描述目标系统的价值需求&#xff0c;可以附上商业模式画布。 1.1 利益相关者 描述目标系统的利益相关者&#xff0c;包括终端用户、企业组织、投资人等。 1.2 系统愿景 描述利益相关者共同达成一致的愿景&#xff0c;该愿景的描述需要对准企业的战略目标。 1.3 系统…...

【JAVASE】封装

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈Java &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 封装 1. 什么是封装2. 访问限定符3. 封装…...

Java多线程(四)

目录 一、线程的状态 1.1 观察线程的所有状态 1.2 线程状态和状态转移的意义 1.2.1 NEW、RUNNABLE、TERMINATED状态转换 1.2.2 WAITING、BLOCKED、TIMED_WAITING状态转换 1.2.3 yield()大公无私让出cpu 一、线程的状态 1.1 观察线程的所有状态 public class Demo9 {public st…...

Linux 文件系统预留空间

在一次磁盘打满的场景下&#xff0c;使用了df -h命令来查看磁盘使用率。 [roottest tmp]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 28G 0 28G 0% /dev tmpfs 28G 0 28G 0% /dev/shm tmpfs 28G 2.8G …...

篇一:单例模式:C++中的独一无二

篇一&#xff1a;“单例模式&#xff1a;C中的独一无二” 设计模式在软件开发中起到了至关重要的作用&#xff0c;其中单例模式是最为常用且基础的设计模式之一。单例模式确保一个类只有一个实例&#xff0c;并提供全局访问点&#xff0c;以保证系统中的某个对象只有唯一的存在…...

JVM之内存结构

1.程序计数器 定义&#xff1a;程序计数器&#xff08;Program Counter Register&#xff09;是JVM中一块较小的内存空间。解释器在解释JVM指令为机器码以供CPU执行时&#xff0c;会去程序计数器当中找到jvm指令的执行地址。 作用&#xff1a;记住下一条jvm指令的执行地址 特…...

C#实现结构体与字节流的相互转化

unity项目中&#xff0c;涉及到与C的相互通信&#xff0c;而通信接口为C封好的动态库。所以&#xff0c;传输信息时&#xff0c;需要向C端发送字节流信息。 对此&#xff0c;需将结构体数据转为字节流&#xff0c;其代码如下&#xff1a; public static byte[] StructToBytes(…...

用LangChain开源框架实现知识机器人

前言 Large Language Models (LLMs)在2020年OpenAI 的 GPT-3 的发布而进入世界舞台 。从那时起&#xff0c;他们稳步增长进入公众视野。 众所周知 OpenAI 的 API 无法联网&#xff0c;所以大家如果想通过它的API实现联网搜索并给出回答、总结 PDF 文档、基于某个 Youtube 视频…...

HCIP——前期综合实验

前期综合实验 一、实验拓扑二、实验要求三、实验思路四、实验步骤1、配置接口IP地址2、交换机配置划分vlan10以及vlan203、总部分部&#xff0c;骨干网配置OSPF分部总部骨干网 4、配置BGP建立邻居关系总部骨干网分部 5、发布用户网段6、将下一跳改为本地7、允许AS重复8、重发布…...

【2023年电赛】运动目标控制与自动追踪系统(E 题)最简单实现

本方案的思路是最简单的不涉及复杂算法&#xff1a;识别矩形框&#xff0c;标记矩形框&#xff0c;输出坐标和中心点&#xff0c;计算长度&#xff0c;控制舵机移动固定长度&#xff01;仅供完成基础功能参考&#xff0c;不喜勿喷&#xff01; # 实现运动目标控制与自动追踪系…...

【IMX6ULL驱动开发学习】22.IMX6ULL开发板读取ADC(以MQ-135为例)

IMX6ULL一共有两个ADC&#xff0c;每个ADC都有八个通道&#xff0c;但他们共用一个ADC控制器 1.设备树 在imx6ull.dtsi文件中已经帮我们定义好了adc1的节点部分信息 adc1: adc02198000 {compatible "fsl,imx6ul-adc", "fsl,vf610-adc";reg <0x0219…...

宝塔安装ModStart,快速开启高效开发之旅!

宝塔面板是一款强大的服务器管理工具&#xff0c;而ModStart则是基于Laravel的模块化快速开发框架&#xff0c;二者的结合将为您的项目开发带来前所未有的便利和高效。在这篇文章中&#xff0c;我们将为您详细介绍如何在宝塔面板上安装ModStart&#xff0c;让您快速搭建功能丰富…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...