单片机学习笔记---蜂鸣器播放提示音音乐(天空之城)

目录

蜂鸣器播放提示音

蜂鸣器播放音乐(天空之城)

准备工作

主程序

中断函数


上一节讲了蜂鸣器驱动原理和乐理基础知识,这一节开始代码演示!

蜂鸣器播放提示音

先创建工程:蜂鸣器播放提示音

把我们之前模块化的程序文件添加进来

但是这次我们 是要静态显示,所以要把Nixie.c文件中这里删掉

我们要实现的效果是我们按下按键之后,会出现按键提示音。

创建一个Buzzer.c和Buzzer.h文件

具体代码解释请看注释:

Buzzer.c

#include <REGX52.H>
#include <INTRINS.H>//_nop_函数的头文件//蜂鸣器端口:普中A2的板子是P2^5,其他板子的可以试试P1^5
sbit Buzzer=P2^5;//在博主以后的博客中,这个函数就作为蜂鸣器的私有延时函数
void Buzzer_Delay500us()		//@12.000MHz
{unsigned char i;_nop_();//延时一微秒的函数i = 247;while (--i);
}//蜂鸣器的发声时长函数
void Buzzer_Time(unsigned int ms)
{unsigned int i;//蜂鸣器翻转的次数for(i=0;i<ms*2;i++)//一个for循环500us=0.5ms,x*0.5ms*2延时xms{Buzzer=!Buzzer;//翻转蜂鸣器//蜂鸣器的标准提示音是1000HzBuzzer_Delay500us();//每500us=0.5ms翻转一次,那蜂鸣响的周期就是1000Hz}
}

Buzzer.h

#ifndef __BUZZER_H__
#define __BUZZER_H__void Buzzer_Time(unsigned int ms);#endif

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Buzzer.h"unsigned char KeyNum;void main()
{Nixie(1,0);//第一位数码管显示0while(1){KeyNum=Key();//按键按下后将键码赋值给keyNumif(KeyNum)//如果按键按下{Buzzer_Time(100);//蜂鸣器响100msNixie(1,KeyNum);//第1位数码管,显示键码}}
}

效果请看视频:

蜂鸣器播放提示音

以上就是蜂鸣器播放提示音的代码演示!

蜂鸣器播放音乐(天空之城)

接下来开始演示蜂鸣器播放音乐(天空之城)

开始之前,我们先接着上一篇解释一下这张表格(我们之后都叫它表1)

  1. 想要的频率在最左边,然后我们不能直接产生频率,我们只有周期,1除以频率就是周期。
  2. 我们需要半个周期给它翻转一次,翻转两次才是一个周期,所以翻转频率就是周期除以2,把这个频率取整就是我们的计数值(需要计这么多的数值然后就产生中断)。
  3. 那么它怎么计这么长呢?溢出才能产生中断对吧?我们就需要给它提前装好中间值(重装载值),在这个值开始计,计到65536溢出就产生中断了。
  4. 为了方便找到对应的音符,我们给这些音符弄个索引,相当于编号。

(PS:手机页面请把表格往左滑动就可看到重装载值)

表1:

音符

频率(Hz)

周期(us)

周期/2(us)

取整

重装载值

索引

1

262

3816.793893

1908.396947

1908

63628

1

1#

277

3610.108303

1805.054152

1805

63731

2

2

294

3401.360544

1700.680272

1701

63835

3

2#

311

3215.434084

1607.717042

1608

63928

4

3

330

3030.30303

1515.151515

1515

64021

5

4

349

2865.329513

1432.664756

1433

64103

6

4#

370

2702.702703

1351.351351

1351

64185

7

5

392

2551.020408

1275.510204

1276

64260

8

5#

415

2409.638554

1204.819277

1205

64331

9

6

440

2272.727273

1136.363636

1136

64400

10

6#

466

2145.922747

1072.961373

1073

64463

11

7

496

2016.129032

1008.064516

1008

64528

12

1

523

1912.045889

956.0229446

956

64580

13

1#

554

1805.054152

902.5270758

903

64633

14

2

587

1703.577513

851.7887564

852

64684

15

2#

622

1607.717042

803.8585209

804

64732

16

3

659

1517.450683

758.7253414

759

64777

17

4

698

1432.664756

716.3323782

716

64820

18

4#

740

1351.351351

675.6756757

676

64860

19

5

784

1275.510204

637.755102

638

64898

20

5#

831

1203.369434

601.6847172

602

64934

21

6

880

1136.363636

568.1818182

568

64968

22

6#

932

1072.961373

536.4806867

536

65000

23

7

988

1012.145749

506.0728745

506

65030

24

1

1046

956.0229446

478.0114723

478

65058

25

1#

1109

901.7132552

450.8566276

451

65085

26

2

1175

851.0638298

425.5319149

426

65110

27

2#

1245

803.2128514

401.6064257

402

65134

28

3

1318

758.7253414

379.3626707

379

65157

29

4

1397

715.8196135

357.9098067

358

65178

30

4#

1480

675.6756757

337.8378378

338

65198

31

5

1568

637.755102

318.877551

319

65217

32

5#

1661

602.0469597

301.0234798

301

65235

33

6

1760

568.1818182

284.0909091

284

65252

34

6#

1865

536.1930295

268.0965147

268

65268

35

7

1976

506.0728745

253.0364372

253

65283

36

接下来开始新创建一个工程:蜂鸣器播放音乐(天空之城)

把之前写好的定时器模块和Delay函数模块添加进来

接下来就对本节代码的每一个模块进行讲解,PS:讲解重点在代码的注释里。

准备工作

为了方便可以重定义端口号(如果最后整个程序写完之后蜂鸣器没有响,那么请看看自己的板子是不是普中的A2开发板,如是,则要把P1^5改成P2^5):

//蜂鸣器端口定义
sbit Buzzer=P1^5;

乐理zhonggu,一个四分音符所用时间是500ms,重定义四分音符的时间,把500ms重命名为Speed:

//播放速度,值为四分音符的时长(ms)
#define SPEED	500

然后我们把表1上的音符与索引重定义:

//音符与索引对应表,P:休止符,L:低音,M:中音,H:高音,下划线:升半音符号#
#define P	0
#define L1	1
#define L1_	2
#define L2	3
#define L2_	4
#define L3	5
#define L4	6
#define L4_	7
#define L5	8
#define L5_	9
#define L6	10
#define L6_	11
#define L7	12
#define M1	13
#define M1_	14
#define M2	15
#define M2_	16
#define M3	17
#define M4	18
#define M4_	19
#define M5	20
#define M5_	21
#define M6	22
#define M6_	23
#define M7	24
#define H1	25
#define H1_	26
#define H2	27
#define H2_	28
#define H3	29
#define H4	30
#define H4_	31
#define H5	32
#define H5_	33
#define H6	34
#define H6_	35
#define H7	36

其中0在乐谱上表示休止符,表示不弹,这里是没有声音的

然后根据表1上的频率和索引弄成一个数组:

//索引与频率对照表
unsigned int FreqTable[]={0,//休止符,表示不弹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,
};

接下来我们就把天空之城的乐谱中的每一个音符放进一个数组中

这是《天空之城》的乐谱:

这里我们定义十六分音符为1个时长(125ms),则八分音符就是2个时长,四分音符就是4个时长(500ms),二音符就是8个时长,全音符就是16个时长。时长即下面写的时值。

//乐谱
unsigned char code Music[]={//音符,时值,//1P,	4,P,	4,P,	4,M6,	2,M7,	2,H1,	4+2,M7,	2,H1,	4,H3,	4,M7,	4+4+4,M3,	2,M3,	2,//2M6,	4+2,M5,	2,M6, 4,H1,	4,M5,	4+4+4,M3,	4,M4,	4+2,M3,	2,M4,	4,H1,	4,//3M3,	4+4,P,	2,H1,	2,H1,	2,H1,	2,M7,	4+2,M4_,2,M4_,4,M7,	4,M7,	8,P,	4,M6,	2,M7,	2,//4H1,	4+2,M7,	2,H1,	4,H3,	4,M7,	4+4+4,M3,	2,M3,	2,M6,	4+2,M5,	2,M6, 4,H1,	4,//5M5,	4+4+4,M2,	2,M3,	2,M4,	4,H1,	2,M7,	2+2,H1,	2+4,H2,	2,H2,	2,H3,	2,H1,	2+4+4,//6H1,	2,M7,	2,M6,	2,M6,	2,M7,	4,M5_,4,M6,	4+4+4,H1,	2,H2,	2,H3,	4+2,H2,	2,H3,	4,H5,	4,//7H2,	4+4+4,M5,	2,M5,	2,H1,	4+2,M7,	2,H1,	4,H3,	4,H3,	4+4+4+4,//8M6,	2,M7,	2,H1,	4,M7,	4,H2,	2,H2,	2,H1,	4+2,M5,	2+4+4,H4,	4,H3,	4,H3,	4,H1,	4,//9H3,	4+4+4,H3,	4,H6,	4+4,H5,	4,H5,	4,H3,	2,H2,	2,H1,	4+4,P,	2,H1,	2,//10H2,	4,H1,	2,H2,	2,H2,	4,H5,	4,H3,	4+4+4,H3,	4,H6,	4+4,H5,	4+4,//11H3,	2,H2,	2,H1,	4+4,P,	2,H1,	2,H2,	4,H1,	2,H2,	2+4,M7,	4,M6,	4+4+4,P,	4,0xFF	//终止标志,防止数组越界之后乱音,用一个最大值来做一个终止标志,也可以设别的值
};

定义两个变量

//FreSelect就是FreqTable[]中的元素的下标,
//MusicSelect就是Music[]中的元素下标unsigned char FreqSelect,MusicSelect;

主程序

void main()
{Timer0Init();//定时器初始化,1ms后溢出调到中断函数中执行中断//之后每次中断函数执行完之后返回主程序中进入while循环while(1){if(Music[MusicSelect]!=0xFF)	//如果不是停止标志位{FreqSelect=Music[MusicSelect];	//选择音符对应的频率//选择好Music[]里的音符(索引/编号的重定义)之后赋值给FreqTable[]的下标FreqSelect,//然后在中断函数里就把FreqSelect这个下标对应的重装载值赋值给TL0和TH0,//也就是让它产生对应的频率即可发出对应的音符MusicSelect++;//Music[]的下标+1就是该音符的时长的下标Delay(SPEED/4*Music[MusicSelect]);	//选择音符对应的时值//SPEED是500ms//SPEED/4=一个十六分音符的时间125ms//125ms*Music[MusicSelect]=125ms*时值=某个音符的时长MusicSelect++;//Music[]的下标+1就是下一个音符的下标//为了停顿后进入下一次while循环的MusicSelect的初值TR0=0;//关闭定时器Delay(5);	//音符间短暂停顿TR0=1;//开启定时器}else	//如果是停止标志位0xFF{TR0=0;//关闭定时器while(1);//程序就一直停在这里了}}
}

中断函数

//如果不是休止符,定时器初始化后第一次进来时是FreqTable[0]=0,没有出声,
//第二次进来中断函数才真正开始选(重装载值)
void Timer0_Routine() interrupt 1 //中断函数每1ms进来一次
{if(FreqTable[FreqSelect])	{/*取对应频率值的重装载值到定时器*/TL0 = FreqTable[FreqSelect]%256;		//设置定时初值TH0 = FreqTable[FreqSelect]/256;		//设置定时初值Buzzer=!Buzzer;	//翻转蜂鸣器IO口}
}

效果请看视频:

蜂鸣器播放音乐

蜂鸣器播放音乐部分完成!

本节的源码放在评论区了,自取!

如有问题,可评论区留言!

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

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

相关文章

第73左侧菜单实现

layout下面新建menu layout index.vue导入menu import Menu from /views/layout/menu菜单实现&#xff1a; <template><el-menuactive-text-color"#ffd04b"background-color"#2d3a4b"class"el-menu-vertical-demo"default-active&quo…

MySQL篇----第二十篇

系列文章目录 文章目录 系列文章目录前言一、NULL 是什么意思二、主键、外键和索引的区别?三、你可以用什么来确保表格里的字段只接受特定范围里的值?四、说说对 SQL 语句优化有哪些方法?(选择几条)前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍…

【ES6】模块化

nodejs遵循了CommonJs的模块化规范 导入 require() 导出 module.exports 模块化的好处&#xff1a; 模块化可以避免命名冲突的问题大家都遵循同样的模块化写代码&#xff0c;降低了沟通的成本&#xff0c;极大方便了各个模块之间的相互调用需要啥模块&#xff0c;调用就行 …

【开源】基于JAVA+Vue+SpringBoot的房屋出售出租系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…

算法-4-归并排序

归并排序 public class Code01_MergeSort {// 递归方法实现public static void mergeSort1(int[] arr) {if (arr null || arr.length < 2) {return;}process(arr, 0, arr.length - 1);}// 请把arr[L..R]排有序// l...r N// T(N) 2 * T(N / 2) O(N)// O(N * logN)public …

C++入门(上)

文章目录 1:什么是C2.C的发展史3:C关键字(C98)4:命名空间4.1:命名空间的概念4.2:命名空间的定义4.3:命名空间的使用4.3.1加命名空间的名称以及域作用限定符4.3.2:使用using将命名空间中某个成员引入4.3.3:使用using namespace 命名空间名称展开命名空间代码1代码2 5:C输入与输出…

Android Jetpack Compose 沉浸式状态栏的实现

目录 概述效果展示代码实现总结 概述 说到沉浸式状态栏&#xff0c;很多小伙伴可能不太熟悉&#xff0c;其实让Android的状态栏的颜色和APP的主题颜色相同&#xff0c;给人感觉状态栏和APP就是一体的。沉浸式的状态栏让页面看起来更舒服&#xff0c;实现沉浸式状态栏也很简单&…

Stable Diffusion 模型下载:DreamShaper(梦想塑造者)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 DreamShaper 是一个分格多样的大模型&#xff0c;可以生成写实、原画、2.5D 等多种图片&#xff0c;能生成很棒的人像和风景图。 条目内容类型大模型基础模型SD 1…

vs2019 - signtool签名和验签的手工操作

文章目录 vs2019 - signtool签名和验签的手工操作概述笔记导入根证书时间戳服务器的选择code sign - 签名文件在代码签名(code sign)前后的区别签名后, 查看属性, 是正常的.用signtool命令行进行验签移除签名END vs2019 - signtool签名和验签的手工操作 概述 signtool是进行c…

django报错:Cannot use ImageField because Pillow is not installed

1、问题概述 ERRORS: accounts.User.avatar: (fields.E210) Cannot use ImageField because Pillow is not installed. HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "python -m pip install Pillow". System check identified 1 …

iOS AlDente 1.0自动防过充, 拯救电池健康度

经常玩iOS的朋友可能遇到过长时间过充导致的电池鼓包及健康度下降问题。MacOS上同样会出现该问题&#xff0c;笔者用了4年的MBP上周刚拿去修了&#xff0c;就是因为长期不拔电源的充电&#xff0c;开始还是电量一半的时候不接电源会黑屏无法开机&#xff0c;最后连着电源都无法…

Lua: 一门轻量级、高效的脚本语言

Lua: 一门轻量级、高效的脚本语言 在当今软件开发的领域中&#xff0c;寻找一门既灵活又高效的脚本语言&#xff0c;一直是开发者们追求的目标。Lua作为一门小巧、高效、可嵌入的脚本语言&#xff0c;已经成为了众多开发者的首选之一。无论是游戏开发、嵌入式系统、Web 开发还是…