【补档_C51单片机】基于C51的蜂鸣器音乐盒工程源码解析(可播放《打上花火》)
项目地址:https://gitee.com/daycen/c51-music-box
通过Keil uVision3打开即可使用
以前做的一些小硬件,现补档至博客
1 功能及总体方案
1.1 功能描述
一个可通过无源蜂鸣器播放任意预先编码好的歌曲的基于51单片机设计的音乐盒。
最小系统部分:由STC89S52单片机X接口连接晶振电路,RESET连接复位电路所构成的满足最简单应用的单片机系统。
无源蜂鸣器驱动电路:由一个1K的分压电阻与无源蜂鸣器串联组成,作为系统的发声源。
软件模块:由计算得出的每个声调的频率数据数组、歌曲编码数组、延时函数、定时器中断函数以及主循环函数构成,用于改变无源蜂鸣器的发声声调。
1.2 系统组成及工作过程
系统组成框图如下:

2 硬件设计
2.1 硬件电路总体设计

单片机最小系统包括单片机、时钟电路、复位电路与5V电源构成,时钟电路提供的时钟信号给单片机提供了一个时间基准。复位电路则是让单片机回到原始状态重新执行程序。
实物图如下:




2.2 模块电路设计
播放一段音乐需要的是两个元素,一个是音调,另一个是音符。首先要了解对应的音调,音调主要由声音的频率决定,同时也与声音强度有关。对一定强度的纯音,音调随频率的升降而升降;对一定频率的纯音、低频纯音的音调随声强增加而下降,高频纯音的音调却随强度增加而上升。另外,音符的频率有所不同。音符的发音主要靠不同的音频脉冲。利用单片机的内部定时器/计数器0,使其工作在模式1,定时中断,然后控制P2.0引脚的输出音乐。只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间,利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。
音乐盒的设计采用STC89C52作为主控芯片,利用单片机内部定时器产生特定的音符频率,控制节拍。
音频模块选用无源蜂鸣器作为发声源,因为它制作成本低,声音频率范围宽,可高分贝的发出某些频率的超声波以及可以做出音符的效果。
PCB图:


3 软件设计
3.1 软件总体设计
软件的总流程图如下

3.2 主程序设计
主程序的设计思路就是将一首乐曲分成三个变量来控制,分别是曲调、所在音区、时长。而控制曲调的因素即频率又分成高八位和第八位两个表,每演奏一个曲调,就根据该曲调的三个变量来取值。此外,x变量用于定义休止符,控制歌曲的不演奏(间断)延时
3.3 各模块程序设计
①音调频率换算
要想产生音频脉冲信号,需要算出某音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用单片机定时器计时这个半周期的时间,每当计时到后就输出脉冲的I/O口反相,这样就在此I/O口上得到此脉冲的频率。
例如,若要产生C大调中的Re(频率为587Hzs)的音频脉冲,其音频信号的脉冲周期T=1/587=1703.5775us,半周期时间为852us,因此总要令计时器计数=852us/1us=852,在每计数852时将I/O口反相,就可以得到Re这个音。按照这种方式可得到一张音符频率对应的半周期数值表,如下图

②歌曲编码
为了能够让程序按照乐谱调用相应的音调数据发声,于是这里我定义了一种编码方式对乐谱进行转换,每个音符的对应的编码包含四个数字:第一个数代表第几个音符(对应简谱中的1234567);第二个数代表第几个八度(音高);第三个数代表时长(以半拍为单位,在钢琴简谱中,音符的右边有一个点代表1.5倍时长);第四个数仅定义为1或0,1表示休止符,间断延时一个节拍而0则不进行任何操作(统一以1121编码代表休止符);
在本程序中,我一共写入了两首歌,分别是《打上花火》和《aLIEz》,在第一首歌播放完毕后会间隔3个节拍的时间播放下一首。特别说明的是,由于编码参考的是钢琴简谱,故编码表中部分时长为3的音符调整为了2目的是让歌曲节奏快一些,且对我对双手谱的复弹做了一定删减以保证听感。
③休止符间断延时函数
该函数由一组双重循环构成,当数组遍历到编码为1121的休止符时,程序会延时a个半拍,模拟出乐谱上休止符的功能。

④主延时函数
与休止符函数类似,主延时函数也由一组双重循环构成,共延时t/2个节拍以控制蜂鸣器发声的时长。此处仅延时t/2个节拍是为了加快歌曲节奏。

⑤定时器中断函数
该函数为T0中断函数。根据图3数值表找到的定时器的初始值被送入这里,无源蜂鸣器被驱动而发声

⑥音乐播放函数
该函数启动T0, 由T0输出方波去发音,并传递参数给图5中的主延时函数,对节拍时长进行控制。

⑦主函数
主程序流程图如下

【补档_C51单片机】基于C51的蜂鸣器音乐盒工程源码解析(可播放《打上花火》)的更多相关文章
- 基于Linux ALSA音频驱动的wav文件解析及播放程序 2012
本设计思路:先打开一个普通wav音频文件,从定义的文件头前面的44个字节中,取出文件头的定义消息,置于一个文件头的结构体中.然后打开alsa音频驱动,从文件头结构体取出采样精度,声道数,采样频率三个重 ...
- 【补档_STM32单片机】脉搏波采集显示硬件设计
一.脉搏波简介 脉搏一般情况下指的都是动脉脉搏.每分钟的脉搏次数称为脉率,正常情况下与心率是一致的.心脏的一次收缩和舒张成为一个心动周期.在每个心动周期内,心室的收缩和舒张会引起脉内压力的周期性波 ...
- 基于Spring注解的上下文初始化过程源码解析(一)
最近工作之余有时间和精力,加上平时对源码比较感兴趣,就开始啃起了Spring源码.为加深印象写了这篇博客,如有错误,望各位大佬不吝指正. 我看的是Spring5的源码,从同性社区download下来后 ...
- 基于Spring注解的上下文初始化过程源码解析(二)
上一篇看完了register方法的代码,继续跟后面代码 后面执行refresh方法,代码清单如下: public void refresh() throws BeansException, Illeg ...
- 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理
服务器文档下载zip格式 刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...
- ARM开发(2)基于STM32的蜂鸣器
基于STM32的蜂鸣器 一 蜂鸣器原理: 1.1 本实验实现1个蜂鸣器间隔1S鸣叫. 1.2 实验思路:根据电路图原理,给蜂鸣器相关引脚赋予高低电平,实现电路的导通,使蜂鸣器实现鸣叫或不鸣. 1 ...
- STL 补档
STL 补档 1.vector 作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. vector在C++标准模板库中的部分内容,它是 ...
- 图论补档——KM算法+稳定婚姻问题
突然发现考前复习图论的时候直接把 KM 和 稳定婚姻 给跳了--emmm 结果现在刷训练指南就疯狂补档.QAQ. KM算法--二分图最大带权匹配 提出问题 (不严谨定义,理解即可) 二分图 定义:将点 ...
- String,StringBuffer和StringBuilder源码解析[基于JDK6]
最近指导几位新人,学习了一下String,StringBuffer和StringBuilder类,从反馈的结果来看,总体感觉学习的深度不够,没有读出东西.其实,JDK的源码是越读越有味的.下面总结一下 ...
- .Net Core 认证系统之基于Identity Server4 Token的JwtToken认证源码解析
介绍JwtToken认证之前,必须要掌握.Net Core认证系统的核心原理,如果你还不了解,请参考.Net Core 认证组件源码解析,且必须对jwt有基本的了解,如果不知道,请百度.最重要的是你还 ...
随机推荐
- JVM启动参数脚本的再学习与研究
JVM启动参数脚本的再学习与研究 摘要 学无止境 前段时间一直再研究JVM参数调优. 但是最近也在想不应该仅研究如何调优. 因为不管怎么设置, 总有猪队友会把环境搞崩. 所以应该想办法在无人值守的情况 ...
- 是否开启raid卡缓存的影响
开启raid卡缓存 Write back 对IO性能的影响 背景 公司买了一台服务器. 想进行一下升级 但是因为管理员担心数据丢失, 使用了write through + (raid6 + hotsp ...
- Redis 的简单学习与整理
Redis 的简单学习与整理 背景 最近一直进行Redis性能调优和高可用的课题 但是不管什么课题,第一步应该是学习与使用redis 之前总结过 rdb 与 rdr 分析 键值对等内容. 但是发现想要 ...
- Oracle DBCA 静默删除以及建库的脚本
No.1 背景 公司最近有一个测试环境需要重新备份恢复 但是里面有6个数据库实例 400多G的数据文件. 一般情况下 需要drop user xxx cascade ; 然后执行 drop table ...
- vue关于通过下标更改数组的理解
案例1:通过下标更改数组失败 <template> <div> <el-button @click="handlerMe2"> 改变 arr & ...
- echarts的初始化和销毁dispose
容器节点被销毁以及被重建时 假设页面中存在多个标签页, 每个标签页都包含一些图表. 当选中一个标签页的时候,其他标签页的内容在 DOM 中被移除了. 这样,当用户再选中这些标签页的时候,就会发现图表& ...
- C# 实现对网站Get与Post请求
C# 是一种面向对象的编程语言,提供了强大的Web请求库和API来执行 HTTP GET 和 POST 请求.在C#中,我们可以使用 System.Net 命名空间下的 WebRequest 和 We ...
- webpack重新打包清空dist文件夹的问题
1.5.20.0以上版本才支持output属性里的clean:true 5.20.0+ 5.20以下版本清除dist文件内容一般使用插件 clean-webpack-plugin, 5.20版本以后o ...
- Eclipse引用第三方jar包中中文注释为乱码问题
1.修改Eclipse中文本文件的默认编码:windows->Preferences->general->Workspace->Textfile encoding设置为UTF- ...
- Spring Boot 参数校验注解(自整理,不停的测试更新)
首先我们只使用java官方的 javax.validation.constraints ,足以使用了,不使用spring boot 自身的,自身的与官方的一致,可能会有扩展,但是还得引入包,麻烦,只用 ...