单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分

有时候我们需要借助单片机实现音乐播放,可行的方案有很多,但成本最低的方案还是通过单片机驱动蜂鸣器来实现音乐播放。本文通过改进常见的单片机驱动蜂鸣器方法,一定程度上实现了任意音乐可以通过蜂鸣器播放(能听出来的程度)。不再需要手动输入乐谱参数,大大节省了时间和提高了准确度。

所用软件

  • keil 5(C51) V5.27.1.0:用于编写、编译C程序并生成hex文件
  • Proteus 8 Professional V8.9:用于单片机仿真

1.根据国际标准音高求出定时器计数值

国际标准音高包含了哆啦咪法嗦来嘻(表中用1234567)的多个音高的频率,为了尽可能的还原音乐,这里模拟了其中9个频率的音高。下表为音高对应的频率。

       接下来根据T=65535-1/频率1/2/1.0851000000+1的公式,在EXCEL表格中添加此公式,可以很快求出各个音高对应的计数值。下图便是上述频率对应的计数值:
       到这里还不算完,因为51单片机定时器计数值分为高位计数值和低位计数值两个部分。所以还需要将上述10进制计数值转为16进制计数值,这样便能直接将2进制的计数值分割成高位和低位两部分。 实现方法很简单,在EXCEL中编辑=DEC2HEX(单元格)便能将对应单元格的10进制计数值转为16进制计数值。下图便是上述10进制计数值对应的16进制计数值:

2.定时器还原音高、延时函数还原音长

为了实现音乐的还原,设计采用定时器中断产生一定频率的方波信号驱动无源蜂鸣器还原音高,延时函数将使该频率维持特定时间还原音长。这样便能实现简谱上一个音符的还原,连贯起来便能还原整段音乐。

  • 2.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.2 添加音乐对应的单片机代码(丁香花)
           其中music[0]为从musicxml中获取到的divisions值(下一节会介绍如何使用)、music[1]为每分钟节拍数、数组结尾放入0表示结束。中间的值按顺序每两个表示一个音高和维持的时间(需要通过换算求出实际时间)。
code unsigned char music[]={8,89,
3,4,4,7,4,4,6,4,4,
7,4,4,6,4,4,6,4,4,
7,4,4,7,4,16,5,4,4,
6,4,4,7,4,4,3,4,4,
5,4,4,3,4,4,5,4,4,
3,4,4,3,4,24,3,4,4,
5,4,4,5,4,4,3,4,4,
5,4,4,6,4,4,6,4,24,
1,5,4,1,5,4,1,5,4,
5,4,4,5,4,4,6,4,4,
7,4,16,7,4,4,3,4,4,
7,4,4,6,4,4,7,4,4,
6,4,4,6,4,4,7,4,4,
7,4,16,7,4,4,3,4,4,
7,4,4,6,4,4,7,4,4,
6,4,4,5,4,4,3,4,4,
3,4,24,3,4,4,5,4,4,
5,4,4,3,4,4,5,4,4,
6,4,4,6,4,16,6,4,4,
7,4,4,1,5,4,1,5,4,
1,5,4,5,4,4,6,4,4,
7,4,4,7,4,24,6,4,4,
5,4,4,6,4,4,5,4,4,
6,4,4,7,4,4,6,4,24,
5,4,4,7,4,4,7,4,4,
6,4,4,6,4,4,5,4,4,
5,4,4,3,4,4,3,4,12,
3,4,4,5,4,4,5,4,4,
5,4,4,5,4,4,5,4,4,
3,4,4,5,4,24,4,4,24,
4,4,24,4,4,24,4,4,24,
4,4,24,3,4,4,4,4,4,
7,4,8,3,5,4,7,4,4,
7,4,8,2,5,4,3,5,4,
3,5,8,3,5,8,3,5,4,
5,5,4,3,5,4,2,5,4,
3,5,4,2,5,4,7,4,4,
6,4,4,7,4,16,3,4,8,
7,4,4,6,4,4,6,4,8,
7,4,4,3,5,4,3,5,4,
5,4,4,5,4,8,7,4,4,
3,5,4,3,5,4,7,4,4,
3,5,4,4,5,4,4,5,4,
7,4,8,3,5,4,7,4,4,
7,4,8,2,5,4,3,5,4,
3,5,8,3,5,8,3,5,4,
5,5,4,3,5,4,2,5,4,
3,5,4,2,5,4,7,4,4,
6,4,4,7,4,16,3,4,8,
7,4,4,6,4,4,6,4,8,
7,4,4,7,4,4,7,4,4,
3,4,4,3,4,8,4,4,8,
4,4,8,4,4,8,6,4,4,
5,4,4,4,4,4,3,4,4,
3,4,4,3,4,16,5,4,12,
6,4,4,6,4,4,7,4,4,
7,4,8,6,4,8,5,4,8,
4,4,2,5,4,4,6,4,8,
3,4,24,3,5,16,7,4,8,
2,5,16,6,4,8,6,4,16,
7,4,8,7,4,16,7,4,8,
1,5,16,1,5,4,2,5,4,
2,5,12,3,5,4,2,5,4,
6,4,4,7,4,8,6,4,4,
7,4,4,7,4,8,6,4,4,
7,4,4,5,4,16,7,4,12,
6,4,4,7,4,4,3,5,4,
2,5,12,6,4,4,6,4,4,
5,4,4,4,4,2,6,4,4,
5,4,4,4,4,4,3,4,24,
3,4,4,7,4,4,6,4,4,
7,4,4,6,4,4,6,4,4,
7,4,4,7,4,16,5,4,4,
6,4,4,7,4,4,3,4,4,
5,4,4,3,4,4,5,4,4,
3,4,4,3,4,24,3,4,4,
5,4,4,5,4,4,3,4,4,
5,4,4,6,4,4,6,4,24,
1,5,4,1,5,4,1,5,4,
5,4,4,5,4,4,6,4,4,
7,4,16,7,4,4,3,4,4,
7,4,4,6,4,4,7,4,4,
6,4,4,6,4,4,7,4,4,
7,4,16,7,4,4,3,4,4,
7,4,4,6,4,4,7,4,4,
6,4,4,5,4,4,3,4,4,
3,4,24,3,4,4,5,4,4,
5,4,4,3,4,4,5,4,4,
6,4,4,6,4,16,6,4,4,
7,4,4,1,5,4,1,5,4,
1,5,4,5,4,4,6,4,4,
7,4,4,7,4,24,6,4,4,
5,4,4,6,4,4,5,4,4,
6,4,4,7,4,4,6,4,24,
5,4,4,7,4,4,7,4,4,
6,4,4,6,4,4,5,4,4,
5,4,4,3,4,4,3,4,12,
3,4,4,5,4,4,5,4,4,
5,4,4,5,4,4,5,4,4,
3,4,4,5,4,24,4,4,24,
4,4,24,4,4,24,4,4,24,
4,4,24,3,4,4,4,4,4,
7,4,8,3,5,4,7,4,4,
7,4,8,2,5,4,3,5,4,
3,5,8,3,5,8,3,5,4,
5,5,4,3,5,4,2,5,4,
3,5,4,2,5,4,7,4,4,
6,4,4,7,4,16,3,4,8,
7,4,4,6,4,4,6,4,8,
7,4,4,3,5,4,3,5,4,
5,4,4,5,4,8,7,4,4,
3,5,4,3,5,4,7,4,4,
3,5,4,4,5,4,4,5,4,
7,4,8,3,5,4,7,4,4,
7,4,8,2,5,4,3,5,4,
3,5,8,3,5,8,3,5,4,
5,5,4,3,5,4,2,5,4,
3,5,4,2,5,4,7,4,4,
6,4,4,7,4,16,3,4,8,
7,4,4,6,4,4,6,4,8,
7,4,4,7,4,4,7,4,4,
3,4,4,3,4,8,4,4,8,
4,4,8,4,4,8,6,4,4,
5,4,4,4,4,4,3,4,4,
3,4,4,3,4,16,7,4,8,
3,5,4,7,4,4,7,4,8,
2,5,4,3,5,4,3,5,8,
3,5,8,3,5,4,5,5,4,
3,5,4,2,5,4,3,5,4,
2,5,4,7,4,4,6,4,4,
7,4,16,3,4,8,7,4,4,
6,4,4,6,4,8,7,4,4,
3,5,4,3,5,4,5,4,4,
5,4,8,4,5,8,7,4,4,
3,5,4,3,5,4,7,4,4,
3,5,6,3,5,1,4,5,4,
7,4,8,3,5,4,7,4,4,
7,4,8,2,5,4,3,5,4,
3,5,8,3,5,8,3,5,4,
5,5,4,3,5,4,2,5,4,
3,5,4,2,5,4,7,4,4,
6,4,4,7,4,16,3,4,8,
7,4,4,6,4,4,6,4,8,
7,4,4,7,4,4,7,4,4,
3,4,4,3,4,8,4,4,8,
4,4,8,4,4,8,6,4,4,
5,4,4,4,4,4,3,4,4,
3,4,4,3,4,16,3,4,4,
7,4,4,6,4,4,7,4,4,
6,4,4,6,4,4,7,4,4,
7,4,16,5,4,4,6,4,4,
7,4,4,6,4,4,6,4,4,
5,4,4,5,4,4,3,4,4,
3,4,24,3,4,4,5,4,4,
5,4,4,3,4,4,5,4,4,
6,4,4,6,4,24,4,4,24,
4,4,24,4,4,24,6,4,4,
5,4,4,4,4,4,3,4,4,
3,4,4,3,4,16,0
};
  • 2.3 音高模拟函数
  • 音高模拟函数实际上就是利用定时器中断产生一定频率方波驱动蜂鸣器发出一定频率的声音。
 void t0int() interrupt 1 //定时器0中断函数
{TR0=0;         //关闭定时器TR0beep=!beep;  //蜂鸣状态取反TH0=timeh;     //把timeh赋给定时0高位计数值TL0=timel;   //把timel赋给定时0低位计数值TR0=1;     //开定时器TR0
}
  • 2.4 音长模拟函数
  • 音长模拟函数实际上就是让音高模拟函数运行一定时间,还原单个音符的发声。
void Delay10ms()     //11.0592MHz下的10ms延时函数
{unsigned char i, j;i = 108;j = 145;do{while (--j);} while (--i);
}
void jiepaidelay(float t)  //节拍延时函数
{unsigned int time;time=sifenyinfu*(t/km); //根据节拍算出10ms的计数次数 for(;time>0;time--){Delay10ms();}TR0=0;
}
  • 2.4 主函数设计
  • 主函数负责协调各个子函数的运作,实现循环播放音乐的功能。
 int main(void)
{float k;unsigned int i;unsigned char m;float n;TMOD=0x01; //置T0定时器工作在方式1EA=1; //开总中断ET0=1; //开定时器0中断,这两句等效于IE=0x82i=2;km=music[0];//获取divisions值paizishu=music[1];    //获取曲子每分钟拍子数k=100*((60/paizishu)/4)+0.5; //根据每分钟节拍数,求解四分之一音符保持时长,四舍五入单位为10ms sifenyinfu=k;//把四分之一音符保持时长值赋给unsigned int型sifenyinfuwhile(1){m=(music[i]-1)*9+music[i+1]; //获取音符对应计数值所在下标n=music[i+2]; //获取音符保持时长值timeh=yingaoh[m]; //获取音符对应定时器计数值高位timel=yingaol[m]; //获取音符对应定时器计数值低位TH0=timeh; //把timeh赋给定时0高位计数值TL0=timel;   //把timel赋给定时0低位计数值TR0=1; //开定时器0jiepaidelay(n); //执行音符保持函数i=i+3;   //读下一个音符if(music[i]==0) i=2;      //如果到末尾则回到开头,循环播放}
}

3.使用Proteus 8 Professional V8.9进行仿真

如果你手边正好没有51单片机,或者你不想动手操作。接下来可以使用Proteus 8 Professional V8.9进行仿真。组成部分很简单,只有单片机和扬声器,注意一定要选择图下所示的扬声器才能发声(为了尽可能还原真实场景,最好把仿真软件中的速度晶振频率调整为11.0592MHz):

单片机通过蜂鸣器播放任意音乐代码实现(1):单片机代码部分相关推荐

  1. 单片机控制蜂鸣器唱生日快乐歌曲 PROTEUS 和51单片机教程(附仿真文件+源代码)

    功能:按一下开关后,单片机控制蜂鸣器唱生日快乐歌曲 PROTEUS 和51单片机教程 单片机控制蜂鸣器唱生日快乐歌曲 程序源代码如下: /* 生日歌 */ #include <reg51.h&g ...

  2. 利用CC2530单片机的蜂鸣器播放音乐的代码

    使用 CC2530 单片机播放音乐需要使用蜂鸣器,这是一个较简单的方法. 下面是一个例子,它使用蜂鸣器播放了著名的<莫扎特第五交响曲>的第一段: #include "ioCC25 ...

  3. 51单片机_11-2 蜂鸣器播放音乐

    文章目录 要求 资源 main函数 要求 控制蜂鸣器播放音乐 资源 工程文件压缩包 链接:https://pan.baidu.com/s/1hA-aa0JRP33IlOYFNzKf7A 提取码:0id ...

  4. (十)51单片机——利用蜂鸣器播放《孤勇者》(附成果展示)

    目录 硬件部分 蜂鸣器介绍 驱动电路 ULN2003 乐理部分 音符 音符与频率对照 代码部分 运行结果 随着最近孤勇者成为小朋友们的接头暗号之后,于是产生了利用单片机去播放孤勇者的想法,接下来我们来 ...

  5. 单片机利用蜂鸣器如何输出音乐

    采用音乐音谱节拍的方式 举个栗子,单片机通过蜂鸣器来播放生日快乐歌. #include "reg51.h" #define uchar unsigned char #define ...

  6. MSP430G2553单片机——利用蜂鸣器播放一首歌

    利用MSP430G2553单片机和无源蜂鸣器播放一首歌,下面给出两种方案. 方案一: 播放<两只老虎> #include<MSP430G2553.h> //音乐播放 // by ...

  7. STM32单片机语音识别MP3播放器音乐播放器TF卡播放器

    实践制作DIY- GC0086-音乐播放器 一.功能说明: 基于STM32单片机设计-音乐播放器 功能介绍: STM32F103C系列最小系统板+语音识别模块+TF卡MP3播放模块+喇叭+3个按键 1 ...

  8. 蜂鸣器播放爱你歌曲c语言程序设计,51单片机控制蜂鸣器播放5首歌曲汇编程序...

    欢乐颂 DB 32,32,32,32,32,32,32,32,32,32,32,32,48,16,64 DB 32,32,32,32,32,16,16,32,32,32,16,16,32,32,32, ...

  9. 51单片机实现蜂鸣器播放小星星

    在中断的时候降了一个调,一开始没发现后面也懒得改了. unsigned int code FreqTable[]={63628,63731,63835,63928,64021,64103,64185, ...

  10. 蜂鸣器播放《两只老虎》

    文章目录 前言 一.回顾蜂鸣器 二.乐谱知识 2.1 音符音频 2.2 两只老虎乐谱 三.系统框图 四.模块调用 五.模块原理图 六.工程源码 6.1 音符选择模块代码 6.2 pwm产生模块代码 6 ...

最新文章

  1. Docker镜像使用
  2. 深层上下文化的单词表示
  3. 若依前后端分离版本,Windows下使用Nginx代理的方式进行部署(全流程,图文教程)
  4. Spring Data ElasticSearch入门案例
  5. java如何对一个表达式开根号_作为一个零基础的新手,如何系统的自学Java和JavaEE开发技术?...
  6. python表情符号编码大全_Emoji的编码以及常见问题处理
  7. 查看NTFS文件系统版本号
  8. WPF中两个窗口的互斥
  9. 读书笔记:《亮剑 .Net》——将类转化为XML并保存已经去读后反序列化为类对象...
  10. Eclipse 真机调试检测不到手机解决方案
  11. linux万能密码,Linux pam 后门纪录root用户密码以及设置万能密码登录root
  12. 解决WPS word论文英文摘要不对齐的问题
  13. Handler内存泄漏-解决:使用静态类和弱引用
  14. 有哪些有用的人际交往小常识?
  15. 利用gpu加速神经网络算法,为什么用gpu 模型训练
  16. centos7配置mysql主从:一主多从
  17. 基于SSM的医院挂号就诊系统
  18. 注册用户数破亿 平安金管家APP成全球寿险首个过亿应用
  19. 快递物流管理系统的设计与实现(SSM,MySQL)
  20. 基于FPGA和ZLG7289实现按键

热门文章

  1. JMeter安装详细教程
  2. 【C++】简易GIF生成器(斗图神器!必备!!!)持续更新~
  3. 数据结构c语言版严蔚敏第二版课后答案
  4. MSDEV.EXE-应用程序错误解决办法
  5. 一、数学建模层次分析法(AHP)【清风数学建模个人笔记】
  6. java的object类型转换_Java Object类型转换
  7. (软考信息安全工程师--中级)二、网络攻击原理与常用方法
  8. FOC电机库 定点PID代码分析
  9. 教你用报表工具搭建企业考核系统
  10. 用JCreator编写java程序