音乐盒设计.docx
《音乐盒设计.docx》由会员分享,可在线阅读,更多相关《音乐盒设计.docx(28页珍藏版)》请在冰豆网上搜索。
![音乐盒设计.docx](https://file1.bdocx.com/fileroot1/2023-5/23/f4c2cf72-afff-4a49-801e-c8d44ec39f23/f4c2cf72-afff-4a49-801e-c8d44ec39f231.gif)
音乐盒设计
目录
摘要…………………………………………………………………………………………2
1引言………………………………………………………………………………………3
2方案设计…………………………………………………………………………………4
2.1音乐盒设计方案论证…………………………………………………………………4
2.1.1方案一……………………………………………………………………………4
2.1.2方案二………………………………………………………………………………4
2.2方案二的总体设计框图………………………………………………………………4
3系统硬件设计……………………………………………………………………………4
3.1主控芯片………………………………………………………………………………4
3.2蜂鸣器及蜂鸣器驱动…………………………………………………………………7
3.3按键……………………………………………………………………………………7
3.4显示设备………………………………………………………………………………8
4系统软件设计……………………………………………………………………………9
4.1基本知识—音调………………………………………………………………………9
4.2基本知识—节拍………………………………………………………………………10
4.3程序流程图……………………………………………………………………………10
4.4程序代码………………………………………………………………………………13
结论…………………………………………………………………………………………21
致谢…………………………………………………………………………………………22
附录A原理图………………………………………………………………………………23
附录B仿真图………………………………………………………………………………24
附录C程序编译图…………………………………………………………………………25
附录DPCB图………………………………………………………………………………26
参考文献……………………………………………………………………………………27
摘要
单片机因其体积小、功能强、价格低廉而得到广泛应用。
本文介绍用AT89C52单片机设计音乐盒的方法,仅需AT89C51最小系统,扩展两个按键,再加一片由两个NPN组成的达林顿管以及输出设备蜂鸣器和LCD。
通过两个按键可以选择上一首歌曲及下一首歌曲,并在LCD上直观的显示出歌曲的序号。
关键词:
音乐盒单片机蜂鸣器LCD
1引言
1.1问题的提出
目前市场上的音乐播放器价格偏高,能否利用现在所学的单片机知识及常见的元器件搭建出能播放简单音乐的电路,将会巩固所学的单片机知识。
1.2任务与分析
本文是应用MCS-51单片机原理和控制理论设计音乐演奏控制器的硬件电路,并利用C语言进行程序设计。
通过控制单片机内部的定时器来产生不同频率的方波,驱动喇叭发出不同音调的音乐,再利用延迟环节延迟一段时间来控制音乐的音调,再通过LCD显示出当前的歌曲名称。
通过查找相关音乐资料把乐谱转化成相应的定时常数就可以从发音设备中演奏出悦耳动听的音乐。
2
方案设计
2.1音乐盒设计方案论证
2.1.1方案一
本设计程序采用定时器0设置节拍,定时器1设置音调。
但是,这种方案需要处理好两个定时器的关系。
比如优先级问题等。
2.1.2方案二
与方案一相比,本方案采用定时器0设置音调,通过延迟一定时间作为节拍。
这种设计不需要考虑两个定时器之间的衔接问题。
编写程序相对简单,更容易实现要求。
2.2方案二总体设计框图
本设计采用89C52作为主控芯片,蜂鸣器作为输出设备产生音乐,通过按键1和2能够选择歌曲。
LCD1602能够实时的显示当前的歌曲名及歌曲号。
其中P3.3和P3.2外接按键,P2口用作LCD输出数据端口,P1.4接蜂鸣器端口。
详细原理图见附件一,仿真图见附件二,程序编译完成图见附件三。
设计框图如图一所示。
图一音乐盒设计框图
3系统硬件设计
3.1主控芯片
设计中所采用主控芯片为AT89C52。
因其价格便宜,在市场上已经很成熟,各个方面都能够满足设计要求故选择它。
其采用标准双列直插式引脚DIP-40大规模集成电路封装。
它的引脚排列如下图二所示
图二AT89C52的引脚排列
引脚介绍:
VCC:
供电电压。
GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
P3口管脚备选功能:
P3.0RXD(串行输入口)
P3.1TXD(串行输出口)
P3.2INT0(外部中断0)
P3.3INT1(外部中断1)
P3.4T0(记时器0外部输入)
P3.5T1(记时器1外部输入)
P3.6WR(外部数据存储器写选通)
P3.7RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。
在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。
因此它可用作对外部输出的脉冲或用于定时目的。
然而要注意的是:
每当用作外部数据存储器时,将跳过一个ALE脉冲。
如想禁止ALE的输出可在SFR8EH地址上置0。
此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。
另外,该引脚被略微拉高。
如果微处理器在外部执行状态ALE禁止,置位无效。
PSEN:
外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。
注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。
在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
XTAL1:
反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:
来自反向振荡器的输出。
振荡器特性:
XTAL1和XTAL2分别为反向放大器的输入和输出。
该反向放大器可以配置为片内振荡器。
石晶振荡和陶瓷振荡均可采用。
如采用外部时钟源驱动器件,XTAL2应不接。
有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。
3.2蜂鸣器及蜂鸣器驱动
蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。
有的压电式蜂鸣器外壳上还装有发光二极管。
电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。
压电式蜂鸣器和电磁式蜂鸣器又各有两种结构:
有源型和无源型。
有源型内部带振荡器,只要一通电就会叫。
而无源蜂鸣器内部不带振荡源,所以如果用直流信号驱动它,将无法令其鸣叫,必须采用2kHz~5kHz的方波信号驱动。
这里从价格及控制上方面,我们选择市场上常见的有源蜂鸣器作为音频输出设备。
达林顿三极管又称复合三极管,它将二只三极管组合在一起,以组成一只等效的新的三极管。
达林顿三极管的放大倍数是二只三极管放大倍数之积。
达林顿三极管可以看作是一种直接耦合的放大器,三极管间以直接方式串接,没有加上任何耦合元件。
这样的晶体管串接型式最大的作用是:
提供高电流放大增益。
两只三极管同为NPN型,将前级三极管的射极电流直接引入下一级的基极,当作下级的输入。
这种使用相同类型的三极管组成的达林顿管称为同极型达林顿管。
由于以上原因,我们选择通过两个NPN三级管搭建成一个达林顿作为为驱动。
如图三所示。
图三三极管组成的达林顿管
3.3按键
采用常用的四引脚按键,其中各有两个引脚相连。
按下时,接通,放开时,将断开。
设计中需要两个按键,作为上一首和下一首的信号输入。
3.3显示设备
为了在播放过程中能够清晰的知道当前歌曲的信息,我们采用市场上常见的LCD1602显示屏作为输入显示设备。
LCD1602为工业字符型液晶,能够同时显示16
02即32个字符。
(16列2行)其液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
1602采用标准的16脚接口,其中:
第1脚:
VSS为电源地
第2脚:
VDD接5V电源正极
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度高会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端。
第7~14脚:
D0~D7为8位双向数据端。
第15~16脚:
空脚或背灯电源。
15脚背光正极,16脚背光负极。
表一元器件清单:
元器件序号
型号
主要参数
数量
备注
R1~R4
10K
3
1/4w
C1、C2
30pF
2
瓷片电容
C3
10uF
1
电解电容
Y1
12MHz
1
晶振
S1~S3
3
按钮
Q1~Q2
2
NPN三极管
LS1
1
有源蜂鸣器
U1
AT89C52
1
单片机
4系统软件设计
4.1基本知识—音调
4.1.1音频脉冲
要生产音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。
利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。
4.1.2方法
利用8051的内部定时器使用其工作在计数器模式MODE1下,改变计数值THO及TLO以产生不同频率的方法。
4.1.3计算公式
例如频率为523Hz,其周期T=1/523=1912us,因此只要令计数器计时956us/1us=956,在每次计数956次时将I/O反相,就可得到中音DO(523Hz)。
计数脉冲值与频率的关系公式如下:
N:
计算值;Fi:
内部计时一次为1us,故其频率为1MHz;
4.1.4其计数值的求法
例如:
设K=65536,F=1000000=Fi=1MHz,求低音DO(261Hz)。
中音DO(523Hz)。
高音的DO(1046Hz)的计算值。
=
低音DO的
中音DO的
高音DO的
4.1.5C调各音符频率与计数值T的对照表如表二所示。
表二C调各音符频率与计数值T的对照表
音符
频率(HZ)
简谱码(T值)
音符
频率(HZ)
简谱码(T值)
低1DO
262
63628
#4FA#
740
64860
#1DO#
277
63731
中5SO
784
64898
低2RE
294
63853
#5SO#
831
64934
#2RE#
311
63928
中6LA
880
64968
低3M
330
64021
#6
932
64994
低4FA
349
64103
中7SI
988
65030
#4FA#
370
64185
高1DO
1046
65058
低5SO
392
64260
#1DO#
1109
65085
#5SO#
415
64331
高2RE
1175
65110
低6LA
440
64400
#2RE#
1245
65134
#6
466
64463
高3M
1318
65157
低7SI
494
64524
高4FA
1397
65178
中1DO
523
64580
#4FA#
1480
65198
#1DO#
554
64633
高5SO
1568
65217
中2RE
587
64684
#5SO#
1661
65235
#2RE#
622
64732
高6LA
1760
65252
中3M
659
64777
#6
1865
65268
中4FA
698
64820
高7SI
1967
4.2基本知识--节拍
4.2.1相关知识
每个音符使用1个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,表三为节拍与节拍码的对照.如果1拍为0.4秒,1/4拍是0.1秒,只要设定延迟时间就可求得节拍的时间.假设1/4拍为1DELAY,则1拍应为4DELAY,以此类推.所以只要求得1/4拍的DELAY时间,其余的节拍就是它的倍数,如表四为1/4和1/8节拍的时间设定。
表三节拍与节拍码对照
节拍码
节拍数
节拍码
节拍数
1
1/4拍
1
1/8拍
2
2/4拍
2
1/4拍
3
3/4拍
3
3/8拍
4
1拍
4
1/2拍
5
1又1/4拍
5
5/8拍
6
1又1/2拍
6
3/4拍
8
2拍
8
1拍
A
2又1/2拍
A
1又1/4拍
C
3拍
C
1又1/2拍
F
3又3/4拍
表四各调1/4节拍的时间设定及各调1/8节拍的时间设定
曲调值
DELAY
曲调值
DELAY
调4/4
125毫秒
调4/4
62毫秒
调3/4
187毫秒
调3/4
94毫秒
调2/4
250毫秒
调2/4
125毫秒
4.3程序流程图
外部中断0中断程序中令Flag2=1,中断1的中断程序中令Flag=1
定时器0中断流程图如图四。
图四定时器0中断流程图
主程序流程图如图五。
图五主程序流程图
4.4程序代码:
KCSJ.C
#include"reg52.h"
#include"LCD.h"
sbitBUZZER=P3^1;
unsignedcharth,tl;
unsignedcharflag2,flag3;
charsong1[14]="NUM1";
charsong2[14]="NUM2";
charsong3[14]="NUM3";
charsong4[14]="NUM4";
//012345678910111213
//7L12345671H2H3H5L6L4L
unsignedint
TONE[14]={1012,956,852,759,716,638,568,506,478,426,379,1276,1136,1433};
//1234567
//低音1908170115151433127611361012
//中音956852759716638568506
//高音478426379358319284253
unsignedcharcodeSONG[4][150]={
//同桌的你
{5,5,5,5,3,4,5,8,6,6,6,6,8,6,5,5,
5,5,5,5,7,6,4,4,4,4,4,4,4,3,2,1,1,
8,8,8,8,5,3,8,8,10,9,9,9,9,8,7,6,6,
7,7,7,7,7,8,9,5,7,7,8,9,8,7,8,8,20},
//一分钱
{5,8,6,8,5,3,5,2,3,5,3,5,6,8,5,6,5,3,
5,1,3,2,3,2,1,2,3,6,5,3,5,6,
5,8,6,5,3,5,2,5,2,3,2,1,20},
//小燕子{3,5,8,6,5,3,5,6,8,5,8,10,9,8,9,8,6,8,5,3,5,6,5,6,8,9,5,6,3,2,1,2,2,2,3,5,5,8,2,3,5,3,5,8,6,5,3,5,6,8,5,8,10,9,8,
9,8,6,8,5,3,5,6,5,6,8,9,5,6,3,8,6,5,3,2,1,2,2,3,5,
8,10,9,8,9,8,5,6,8,20},
//两只老虎{1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,4,3,1,
2,11,1,2,11,1,20}};
unsignedcharcodeBEAT[4][150]={{4,4,4,4,4,4,8,8,4,4,4,4,4,4,8,4,
4,4,4,4,4,4,8,8,4,4,4,4,4,2,8,8,
4,4,4,4,4,4,8,4,8,4,4,4,4,2,4,8,8,
4,4,4,4,4,4,8,8,4,4,4,4,4,4,8,8},
{8,8,4,4,8,4,4,4,4,8,4,4,4,4,4,4,4,4,
4,8,4,8,4,4,4,4,16,4,4,4,4,8,
4,4,4,4,4,4,8,4,4,4,4,16},
{4,4,4,4,16,4,4,4,4,16,8,4,8,8,4,4,4,4,16,8,4,8,4,4,8,4,4,16,4,4,8,16,8,4,4,8,8,8,4,4,16,4,4,4,4,16,4,4,4,4,16,8,4,8,8,
4,4,4,4,16,8,4,8,4,4,8,4,4,16,8,4,8,8,4,4,8,16,8,4,16,
8,4,8,8,4,4,4,4,16},{4,4,4,4,4,4,4,4,4,4,8,4,4,8,2,2,2,2,4,4,2,2,2,2,4,4,4,
4,8,4,4,8}};
voiddis_song(chara);
/*****************设置音调*******************/
//对定时器0的初始值更新
voidSET_BUZZER_TONE(unsignedinttone)
{
TR0=0;
th=(65536-tone)/256;
tl=(65536-tone)%256;
TR0=1;
}
/**************设置节拍**********************/
//x为最小节拍的倍数
voidDELAY_MIN_BEAT(unsignedcharx)
{
unsignedinti,j,k;
for(i=0;i{
for(j=0;j<100;j++)
for(k=0;k<120;k++);
}
TR0=0;
}
/***************定时器0初始化****************/
voidTIME0_INIT()
{
IE|=0x82;
TMOD=0x01;//定时器0工作在方式1
IP=0x02;//定时器0具有最高优先级
}
/**************外部中断0和1初始化***********/
voidINT_INIT()
{
IE|=0x85;
TCON|=0x05;//外部中断0和1负边缘触发
}
/****************主函数*********************/
voidmain()
{
charnum1,num2;
unsignedcharflag1;
num1=0;
num2=0;
flag1=1;
flag2=0;
flag3=0;
BUZZER=0;
TIME0_INIT();//定时器初始化
INT_INIT();//外部中断初始化
LCD_INIT();//LCD初始化
while
(1)
{
dis_song(num1);
while(flag1)
{
if(SONG[num1][num2]==20)flag1=0;//如果检测到最后一个音调为20,说明此曲应该结束
else
{if(flag2==1)//中断检测
{
num1++;
if(num1>3)num1=0;
num2=0;
flag2=0;
dis_song(num1);
}
if(flag3==1)//中断检测
{
num1--;
if(num1<0)num1=3;