目录

蜂鸣器介绍

驱动电路

三极管驱动

集成电路驱动

音乐的相关知识

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

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

实际代码演示:


蜂鸣器介绍

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

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

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

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

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

驱动电路

三极管驱动

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

集成电路驱动

我们开发板上的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的宏定义可以根据自己的喜好来定义哦,700只是一个参考数值

#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"//蜂鸣器端口定义
sbit Buzzer=P2^5;//播放速度,将一个四分音符的时长设置为700(ms),并以四分音符的时长为基准
#define SPEED   700//音符与索引对应表,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)//音符,时值,//1
//  M3,8,
//  P,4,
//  P,1,
//  M1,1,
//  M2,1,
//  M1,1,
//
//  //2
//  M3,8,
//  P,3,
//  M1,1,
//  M2,1,
//  M1,1,
//  M2,1,
//  M3,1,
//
//  //3
//  L6,3,
//  M1,1,
//  L6,3,
//  M1,1,
//  L6,3,
//  M1,1,
//  M3,2,
//  M1,2,
//
//  //4
//  L7,8,
//  L6,1,
//  M1,1,
//  M6,2,
//  M6,1,
//  M6,1,
//  M6,1,
//  M5,5,
//  M6,2,
//  M6,1,
//  M5,1,
//  M6,1,
//  M5,1,
//  M6,1,
//  M5,1,
//
//  //5
//  M3,1,
//  M3,3,
//  M3,4,
//  P,4,
//  P,2,
//  L6,1,
//  M1,1,
//
//  //6
//  M6,3,
//  M6,1,
//  M6,1,
//  M5,1,
//  M6,1,
//  M5,1,
//  M7,3,
//  M7,1,
//  M7,1,
//  M6,2,
//  M7,1,
//
//  //7
//    M7,1,
//  M6,2,
//  M3,1,
//  M3,8,
//  P,1,
//  M3,1,
//  M5,1,
//  M3,1,
//
//  //8
//    M2,3,
//  M3,1,
//  M2,3,
//  M3,1,
//    M2,3,
//  M3,1,
//    M5,1,
//  M3,1,
//  M5,1,
//  M3,1,// //9
//    M2,3,
//  M3,1,
//    M2,3,
//  M3,1,
//  M2,4,
//  P,2,
//  M1,1,
//  M2,1,
//
//  //10
//    M3,2,
//  L6,2,
//  M1,2,
//  M3,2,
//  M2,3,
//  M3,1,
//  M2,1,
//  M1,1,
//  M1,2,
//
//  //11
//    L6,8,
//  P,4,
//  P,2,
//  M6,1,
//  M7,1,//---------高潮部分----------////12H1,1,H2,1,M7,1,H1,1,H1,2,H1,1,M7,1,H1,1,H2,1,M7,1,H1,1,H1,2,H1,1,H2,1,//13H3,1,H2,1,H3,1,H2,1,H3,2,H3,1,H2,1,H3,2,H5,2,H3,2,M6,1,M7,1,//14H1,1,H2,1,M7,1,H1,1,H1,2,H1,1,M7,1,H1,1,H2,1,M7,1,H1,1,H1,2,H1,1,M7,1,//15H3,1,H2,1,H3,1,H2,1,H3,2,H3,1,H2,1,H3,2,H5,2,H3,2,H5,2,//16H3,3,H5,1,H3,3,H5,1,H3,1,H5,1,H6,1,H3,1,H5,2,H5,2,//17H3,3,H5,1,H3,3,H5,1,H3,1,H5,1,H6,1,H3,1,H5,2,H5,1,H5,1,//18H3,1,H2,1,H2,2,H2,2,H1,1,H3,1,H3,1,H2,1,H2,2,H2,2,H1,1,H1,1,//19M6,8,P,4,P,2,H5,1,H5,1,//20H3,1,H2,1,H2,2,H2,2,H1,1,H3,1,H3,1,H2,1,H2,2,H2,2,H1,1,H1,1,//21M6,8,P,4,P,4,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. ELK安装配置,日志展示
  2. ARTS打卡计划第一周-Share-系统字典模块的设计
  3. 第一课 前言 学PHP就是为了做网站
  4. 基于Verilog的按键控制LED灯
  5. Asp.net ajax、Anthem.net、Ajax pro三大ajax框架论坛网友比较
  6. python 爬取_使用 Python 和 BeautifulSoup 来做爬虫抓取
  7. 《Reids 设计与实现》第十二章 复制
  8. 【aviator】aviator 报错 EOF while reading string at index
  9. distri.lua的web运维工具
  10. Visio2013 Professional专业版密钥
  11. html字体设置匹配移动端,移动端字体的设置
  12. 反编译DLL。并且修改DLL内容
  13. Java版进销存ERP管理系统源码
  14. js 编写一个程序实现统计一串字符串中的英文小写字母个数!
  15. 局域网共享文件夹/共享文件夹无法访问解决办法
  16. 2022电大国家开放大学网上形考任务-实用卫生统计学非免费(非答案)
  17. Android培训班 4
  18. Vue学习-常用属性(一)
  19. 积极推动上市银行 进入交易所债市
  20. 网站变灰 filter: grayscale(100%);

热门文章

  1. java获取当前上一周、上一月、上一年的时间dxl
  2. 不确定度在线计算_国睿认证干货来啦:实验室CNAS认可常见问题集锦(五):关于不确定度...
  3. C#建立手机号段全库
  4. Java商城项目实战
  5. Pycharm设置中文版
  6. 临近毕业,查降重来了
  7. 【离散数学】数理逻辑 第二章 谓词逻辑(3) 谓词公式的逻辑等价与蕴含、谓词演算的永真公式
  8. 股票交易数据下载 | 下载股票历史交易数据到本地Excel
  9. 新版Excel和Word全屏打印预览的设定方法
  10. Unity3D 下载与安装