目录

蜂鸣器介绍

驱动电路

三极管驱动

集成电路驱动

音乐的相关知识

音符与计时器重装载值对应表

将乐谱转换为宏定义的音调谱

实际代码演示:


蜂鸣器介绍

蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音、报警音等提示信号

蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器

有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

这里显然我们单片机上面的蜂鸣器是无源蜂鸣器,需要我们手动编写代码为其配置振荡脉冲的频率,而使其发出不同的音调。

驱动电路

三极管驱动

左图为高电平导通,右图为低电平导通

集成电路驱动

我们开发板上的ULN2003D驱动芯片的OUT1~~OUT4是用来驱动电机的,自然OUT5是用来驱动蜂鸣器的(BEEP),最后OUT6,7没有接线(之所以这样都是为了节约引脚口而考虑)

音乐的相关知识

我了解的也不多,所以可能有错的请大家见谅:

一个曲子简单的是由音调节拍决定的,音调是什么1,2,3,4,5,6,7这些数字,也就是大家熟悉的。然后节拍是什么4分音符,8分音符。也就是音调持续的时间长短。

那么如何在蜂鸣器上模拟出各种各样的音调呢,首先是要知道不同音调有不同的频率,所以我们只要设法精确的将频率的信号输入到蜂鸣器就行

观察规律我们发现:每个音符满足12平分率

(前面一个音符的频率)*2^(1/12)=(后面一个音符的频率)

或者说(后面一个音符的频率)/{2^(1/12)}=(前面一个音符的频率)

那么频率的公式为f=1/T,我们可以发现相邻音调之间就差那么十几赫兹,所以要求的精度还是比较高的,所以我们用定时器来计时,得到精确的频率脉冲。

之前学过波的相关知识,一个波形要有波峰和波谷才算一个完整的周期,所以我们在音符频率对应的周期内要将蜂鸣器的电压翻转2次。为了使定时器方便编码(不能说计时一半还没溢出就进行中断,来进行翻转),我们在以一个音调周期一半为一个单位进行计时并中断来翻转蜂鸣器,然后就实现了一个周期翻转2次的目的。

音符与计时器重装载值对应表

将低音L1为示例:T=1/f=1/262=0.0038167938931298,Tx1000000=3,816.793893129771

T/2=1,908.396946564885,取整1908,重装载值=65536-T/2=63628

有了这个表以后就可以先将音符宏定义(例如高音用H开头,低音用L开头),然后创建一个数组将音符与对应的重装载值对应即可;

将乐谱转换为宏定义的音调谱

以天空之城简谱的节选为例,简单说明一下谱子里面包含的信息:

下面我来写天空之城的第一行的音符,我以一个一分音符为时间基准,那么一节有4拍就是四个四分音符16

(将空音符定义为P,高音用H开头,低音用L开头,中央音符用M开头)

//第一小节P, 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,

这样一来将乐谱建立一个数组,那么音调与节拍就交替存在了,这样就方便调用

注意:还有一点就是,那个不同音调之间要有停顿感,为了实现这一目的所以在实际操作的时候,每个音符演奏以后,要将定时器延时5~10ms再进行下一个音符的演奏

主函数代码分析:

我们配置的中断函数主要是用使蜂鸣器以不同的频率翻转从而发声,所以重装载值普遍还是比较小的,可以认为时时刻刻都在执行中断服务函数。

FreqSelect=Music[MusicSelect];
MusicSelect++;

是根据我们写的谱子的奇数位的元素来调用Music[]中的重装载值,写入到中断服务函数中,从而改变中断的时间,进而改变蜂鸣器的发音频率

Delay(SPEED/4*Music[MusicSelect]);
MusicSelect++;

是用来模拟谱子中节拍的问题,在Delay函数进行的时候,中断函数的重装载值一直是同一个,这样就实现了同一个音的持续发生

TR0=0;
Delay(5);
TR0=1;

不同音符间短暂停顿,利用延时开关定时器实现。如果没有这个操作的话,声音就是那种连续的,像是一口气唱歌一样。所以短暂中断实有必要

实际代码演示:

音乐《卡农》片段

主函数:

ps:SPEED的宏定义可以根据自己的喜好来定义哦,600只是一个参考数值

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"//蜂鸣器端口定义
sbit Buzzer=P2^5;//播放速度,将一个四分音符的时长设置为600(ms),并以四分音符的时长为基准
#define SPEED   600//音符与索引对应表,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//索引与频率对照表
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,
};//乐谱
unsigned int code Music[]={//乐谱较长加上关键字code将其储存在ROM(flash)//音符,时值,//1H5,2,H3,1,H4,1,H5,2,H3,1,H4,1,H5,1,M7,1,M6,1,M7,1,H1,1,H2,1,H3,1,H4,1,//2H3,2,H1,1,H2,1,H3,2,M3,1,M4,1,M5,1,M6,1,M5,1,M4,1,M5,1,H1,1,M7,1,H1,1,//3M6,2,H1,1,M7,1,M6,2,M5,1,M4,1,M5,1,M4,1,M3,1,M4,1,M5,1,M6,1,M7,1,H1,1,//4M6,2,H1,1,M7,1,H1,2,M7,1,H1,1,M7,1,M6,1,M7,1,H1,1,H2,1,H3,1,H4,1,H5,1,//5H5,2,H3,1,H4,1,H5,2,H3,1,H4,1,H5,1,M7,1,M6,1,M7,1,H1,1,H2,1,H3,1,H4,1,//6H3,2,H1,1,H2,1,H3,2,M3,1,M4,1,M5,1,M6,1,M5,1,M4,1,M5,1,H1,1,M7,1,H1,1,0xFF    //终止标志
};unsigned int FreqSelect,MusicSelect;//MusicSelect为乐谱数组下标,FreqSelect音调宏定义void main()
{Timer0Init();while(1){if(Music[MusicSelect]!=0xFF)    //如果不是停止标志位{FreqSelect=Music[MusicSelect]; //选择音符对应的频率MusicSelect++;Delay(SPEED/4*Music[MusicSelect]);   //选择音符对应的时长MusicSelect++;TR0=0;//不同音符间短暂停顿,利用延时开关定时器实现Delay(5);   TR0=1;}else    //如果是停止标志位{TR0=0;  //关闭定时器while(1);}}
}void Timer0_Routine() interrupt 1
{if(FreqTable[FreqSelect])  //如果是休止符(0),那么不播放声音,只进行延时{//取对应频率值的重装载值到定时器(确认音高)FreqSelect=Music[MusicSelect]TL0 = FreqTable[FreqSelect]%256;      //设置低位定时初值TH0 = FreqTable[FreqSelect]/256;     //设置高位定时初值Buzzer=!Buzzer;  //翻转蜂鸣器IO口(注意这里的重装值是周期的一半,故仅进行一次蜂鸣器的翻转)}
}

定时器:

.h文件

#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0Init(void);#endif

.c文件

void Timer0Init(void)
{TMOD &= 0xF0;     //设置定时器模式TMOD |= 0x01;     //设置定时器模式TL0 = 0x18;       //设置定时初值TH0 = 0xFC;        //设置定时初值TF0 = 0;       //清除TF0标志TR0 = 1;      //定时器0开始计时ET0=1;EA=1;PT0=0;
}

延时函数Delay()

.h文件

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int xms);#endif

.c文件

void Delay(unsigned int xms)
{unsigned char i, j;while(xms--){i = 2;j = 239;do{while (--j);} while (--i);}
}

还有就是,如果出现问题,那么请您及时检查一下自己是不是有如下问题:
1,蜂鸣器是否为无源的;

2,蜂鸣器的引脚是否为P2^5;

3,演奏音乐对时序要求高,中间不可以穿插运行别的程序,至少我反复尝试是这样的;

如果想要边放音乐,边运转一个步进电机啊什么的,建议将音乐模块单独拿出来,不如我有写过语音模块JQ8900-16P的使用方法,对于新手非常好,虽然有些大材小用,但是我个人认为还是比较方便的;

链接如下:

JQ8900-16P模块的配置与使用

啰啰嗦嗦这么多,到这里就算写完了,若有不当之处,恳请指正!
对了,还有什么想用单片机听的音乐,可以在评论区留言哦,会尽快更新的,玩的开心!!

STC89C52单片机蜂鸣器介绍以及《卡农》歌曲代码示例相关推荐

  1. STC89C52单片机DS1302介绍以及代码示例

    目录 DS1302介绍 引脚定义与应用电路 内部结构框架图 寄存器定义 时序定义 BCD码 时间设置上的一些问题 代码示例: DS1302介绍 DS1302是由美国DALLAS公司推出的具有涓细电流充 ...

  2. matlab演奏《卡农》代码

    clear %% 程序配置 global fs global trail global fff global fdb fs = 44100; trail = 0/15; % 长唢呐频谱 fff = [ ...

  3. 【NLP】pyltp工具介绍、安装和使用代码+示例

    [NLP]pyltp工具介绍.安装和使用pyltp 文章目录 [NLP]pyltp工具介绍.安装和使用pyltp 1. 介绍 2. 使用 2.1 分句 2.2 分词 2.3 词性标注 2.4 命名实体 ...

  4. 基于STC89C52单片机的密码锁设计与实现

    目 录 一.引言 3 1.1 课题研究背景及意义 3 1.2 课题设计的目的以及主要内容 4 二.系统硬件设计 5 2.1.系统硬件总体设计 5 2.2 单片机型号的选择 6 1.STC89C52单片 ...

  5. stc89c52c语言开发,STC89C52单片机开发板入门教程——简介(致雅科技)

    ZY_STC89C52开发板提供了以下的实验源代码和相关说明文档,帮助广大初学者快速的掌握STC89C52单片机的使用方法,开发者可以基于示例代码开发自己的应用,加快产品开发进度,节省宝贵的开发时间. ...

  6. matlab卡农,又用Mathematica写了一段卡农

    你能在这里听到它 用数学软件演奏音乐早已不是什么新鲜事,很早就有人用Matlab弹奏卡农或是最炫民族风,最近我知道还有人用无理数生成一段音乐,很有趣.而我选择用Mathematica弹奏卡农是因为卡农 ...

  7. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  8. 【SHQi——单片机系列(一)】| STC89C52单片机 | 入门向 | 单片机系列介绍

    单片机系列介绍 1.什么是单片机 单片机,全称:单片微型计算机(Single Chip Microcomputer) 英文:Micro Controller unit,简称为 MCU 是一种集成电路芯 ...

  9. STC89C52单片机矩阵LED灯介绍以及代码示例

    目录 一,LED点阵屏介绍 二,显示原理 三,74HC595以及LED点阵屏 74HC595寄存器的介绍: 74HC595寄存器的使用方法: 74HC595以及LED点阵屏原理图: 四,开发板引脚对应 ...

  10. stc89c51单片机音乐盒系统设计_基于STC89C52单片机的七彩迷你音乐盒

    基于STC89C52单片机的七彩迷你音乐盒.在单片机最小系统的基础上,对其他两个I/O口连接硬件电路.P1.0接一个七彩快闪LED灯.P1.5口接一个NPN型三极管的放大电路,再连接一个无源蜂鸣器(用 ...

最新文章

  1. 关于while 和if
  2. python编程与特征提取_Python进行特征提取的示例代码
  3. 【NLP】Sentence-T5|谷歌提出文本表示新SOTA
  4. 【Linux】一步一步学Linux——ssh-add命令(182)
  5. js处理异常try{}catch(e){}
  6. FTP下载导致Zip解压失败的原因
  7. Replication的犄角旮旯(一)--变更订阅端表名的应用场景
  8. python 生成嵌套字典
  9. 安装alexa工具条报毒
  10. FPN网络结构及Pytorch实现
  11. C# 将Big5繁体转换简体GB2312的代码
  12. Android虚拟机参数
  13. 连接重置Connection reset异常
  14. [NOIP2018 普及组] 龙虎斗
  15. pve安装黑群晖直通硬盘_Promox VE(PVE)安装虚拟黑群晖实现硬盘休眠避坑指南
  16. 337调查之「普遍排除令」简介及2018年度典型案例探讨
  17. 太酷了!我老了之后,也要这么“兴风作浪”!
  18. ASP.NET 权限管理 页面静态化 OA系统培训 三层架构
  19. 【电工基础】电路的基本概念与基本定律
  20. 通过python理解光的偏振

热门文章

  1. 破解Visio时office失效,激活失败
  2. VMware 虚拟机安装系统
  3. python线程池和多线程
  4. 俄罗斯方块代码(自写)
  5. 地震及断层分析相关软件
  6. python命令行清屏的简单办法_Python Shell 清屏方法
  7. 微信小程序开发(十二)小程序画布组件canvas
  8. ST电机库无感FOC模式接电机前准备工作(1)----PWM波的生成
  9. JAVA JDK API(中文) 1.6、1.8
  10. 数字信号处理----数字上变频和下变频都FPGA实现