数字音乐盒的设计与实现.docx

上传人:b****8 文档编号:9454603 上传时间:2023-05-19 格式:DOCX 页数:27 大小:250.63KB
下载 相关 举报
数字音乐盒的设计与实现.docx_第1页
第1页 / 共27页
数字音乐盒的设计与实现.docx_第2页
第2页 / 共27页
数字音乐盒的设计与实现.docx_第3页
第3页 / 共27页
数字音乐盒的设计与实现.docx_第4页
第4页 / 共27页
数字音乐盒的设计与实现.docx_第5页
第5页 / 共27页
数字音乐盒的设计与实现.docx_第6页
第6页 / 共27页
数字音乐盒的设计与实现.docx_第7页
第7页 / 共27页
数字音乐盒的设计与实现.docx_第8页
第8页 / 共27页
数字音乐盒的设计与实现.docx_第9页
第9页 / 共27页
数字音乐盒的设计与实现.docx_第10页
第10页 / 共27页
数字音乐盒的设计与实现.docx_第11页
第11页 / 共27页
数字音乐盒的设计与实现.docx_第12页
第12页 / 共27页
数字音乐盒的设计与实现.docx_第13页
第13页 / 共27页
数字音乐盒的设计与实现.docx_第14页
第14页 / 共27页
数字音乐盒的设计与实现.docx_第15页
第15页 / 共27页
数字音乐盒的设计与实现.docx_第16页
第16页 / 共27页
数字音乐盒的设计与实现.docx_第17页
第17页 / 共27页
数字音乐盒的设计与实现.docx_第18页
第18页 / 共27页
数字音乐盒的设计与实现.docx_第19页
第19页 / 共27页
数字音乐盒的设计与实现.docx_第20页
第20页 / 共27页
亲,该文档总共27页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

数字音乐盒的设计与实现.docx

《数字音乐盒的设计与实现.docx》由会员分享,可在线阅读,更多相关《数字音乐盒的设计与实现.docx(27页珍藏版)》请在冰点文库上搜索。

数字音乐盒的设计与实现.docx

数字音乐盒的设计与实现

 

课程设计报告

课程设计名称:

微机系统综合课程设计

课程设计题目:

数字音乐盒的设计与实现

1总体设计方案

1.1题目介绍与要求

本次课程设计的任务是运用伟福Lab8000试验箱和keil软件设计并实现一个数字音乐盒,要求采用I/O产生一定频率的方波,从而驱动蜂鸣器发出不同的音调,演奏乐曲;并且需要采用七段数码管显示当前播放的歌曲序号和播放时间;还得通过数字键盘直接选择乐曲,控制选择上一曲和下一曲音乐,具有暂停和播放控制功能。

1.2设计思路

1.2.1音调的产生

频率的高低决定了音调的高低。

音乐的十二平均率规定:

每两个八度音(如简谱中的中音1和高音1)之间的频率相差一倍。

在两个八度音之间又分为十二个半音。

另外,音名A(简谱中的低音6)的频率为440Hz,音名B到C之间、E到F之间为半音,其余为全音。

由此可以计算出简谱中从低音1到高音1之间每个音名对应的频率,所有不同频率的信号都是从同一个基准频率分频得到的。

要产生音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。

利用定时器计时这半个周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。

利用51单片机的内部定时器使其工作在计数器模式MODE1下,改变计数值TH0与TL0以产生不同频率的方法。

此外结束符和休止符可以分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;若查表结果为FFH,则产生相应的停顿效果。

例如频率为523Hz,其周期T=1/523=1912us,因此只要令计数器计时956us/1us=956,在每次技术956次时将I/O反相,就可得到中音DO(523Hz)。

计数脉冲值与频率的关系公式如下:

N:

计算值;Fi:

内部计时一次为1us,故其频率为1MHz;

其计数值的求法如下:

C调各音符频率与计数值T的对照表如表1.1所示。

 

表1.1C调各音符频率与计数值T的对照表

低音

频率

N

参数

中音

频率

N

参数

高音

频率

N

参数

Do

262

1908

229

Do

523

956

115

Do

1046

57

57

Do#

277

1805

217

Do﹟

554

903

108

Do﹟

1109

54

54

Re3

294

1701

204

Re

587

852

102

Re

1175

51

51

Re﹟

311

1608

193

Re﹟

622

804

97

Re﹟

1245

48

48

Mi

330

1515

182

Mi

659

759

91

Mi

1318

45

45

Fa

349

1433

172

Fa

698

716

86

Fa

1397

43

43

Fa﹟

370

1351

162

Fa﹟

740

676

81

Fa﹟

1480

41

41

So

392

1276

153

So

784

638

77

So

1568

38

38

So﹟

415

1205

145

So﹟

831

602

72

So﹟

1661

36

36

La

440

1136

136

La

880

568

68

La

1760

34

34

La﹟

464

1078

129

La﹟

932

536

64

La﹟

1865

32

32

Si

494

1012

121

Si

988

506

61

Si

1976

30

30

1.2.2节拍的产生

构成音乐需要节拍,让音乐具有旋律,而且可以调节各个音的快慢度。

若1拍实0.5s,则1/4拍为0.125s。

至于1有多长时间,可以按照设计者来决定,只要好听就行。

音持续时间的长短即时值,一般用拍数表示。

休止符表示暂停发音。

一首音乐是由许多不同的音符组成的,而每个音符对应着不同频率,这样就可以利用不同的频率的组合,加以与拍数对应的延时,构成音乐。

节拍与节拍码对照表如表1.2所示。

 

表1.2节拍与节拍码对照

节拍码

节拍数

节拍码

节拍数

1

1/4拍

1

1/8拍

2

2/4拍

2

1/4拍

3

3/4拍

3

3/8拍

4

1拍

4

2/1拍

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位代表音符的高低,低4位代表音符的节拍。

如果1拍为0.4秒,1/4拍为0.1秒,只要设定延迟时间就可求得节拍的时间。

假设1/4拍的延迟时间为1,则1拍的延迟时间应为4,以此类推。

所以只要求得1/4拍的延迟时间,其余的节拍就是它的倍数。

表1.3所示。

表1.31/4和1/8节拍的时间设定

曲调值

DELAY

曲调值

DELAY

调4/4

125毫秒

调4/4

62毫秒

调3/4

187毫秒

调3/4

94毫秒

调2/4

250毫秒

调2/4

125毫秒

 

2硬件电路设计

2.1系统原理

数字音乐盒的核心主要分为三个方面,分别是七段数码管、键盘和蜂鸣器。

用定时器中断的方式来控制蜂鸣器和扫描4*4键盘,在程序中用显示函数让数码管显示,需要显示出歌曲序号和播放时间,并且能用键盘控制播放的音乐。

原理框图如图2.1所示。

图2.1系统原理框图

2.2单片机

8051单片机是在课堂上学习的单片机型号,也是这次课程设计的核心器件,它是8位的单片机,具有品种全、兼容性强、性能价格比高等特点。

8051单片机具有很多的I/O口,其中P2.4、P2.5、P2.6连接74LS138译码器,而译码器则可以控制片选信号和位选信号;P0的八个I/O口要与译码器74HC374相连,然后在与键盘连接,从而能确认数码管的段选信号,此次课程设计的位选码为0x8002。

段选码是0x8004;P1.1口则控制的是蜂鸣器。

单片机电路图如图2.2所示。

图2.2单片机电路图

2.3主要电路器件

2.3.1蜂鸣器

蜂鸣器是整个电路中重要的输出部分之一,没有了蜂鸣器就不会响起悦耳的音乐,本次课程设计,运用了单片机I/O口中的P1.1口,当程序中的play变量等于1时,蜂鸣器响,反之,若play等于0,则停止响声。

端口输出的方波经放大滤波后,驱动蜂鸣器发声,蜂鸣器的电路图如图2.3所示。

图2.3蜂鸣器电路图

2.3.2键盘

Lab8000实验箱内的键盘是4*6的键盘,但是这次课程设计只用到了前四列,所以也就只扫描了四列按键,键盘的主要功能就是用户的输入,也是实现程序现象的重要部分,当用户想播放哪首歌曲就在键盘中输入哪个按键。

实验箱内的键盘还连接了一个ULN2003芯片,这个芯片的特点是电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于要求高速大功率驱动的系统。

键盘的电路图如图2.4所示。

图2.4键盘电路图

2.3.3数码管

此次课程设计运用了六的数码管,第一个显示了歌曲的序号,第二个是空位,第三和第四个显示了分钟的计时,第五和第六个显示了秒钟的计时。

数码管的主要作用就是显示出当前程序运行时的现象,数码管的位选位与ULN2003相连后再接到键盘上,段选位则是连到74HC374译码器上,实验箱的数码管为共阴极,显示方式为动态显示。

由电路图得知,位选信号为1时有效。

数码管示意图如图2.5所示。

图2.5数码管示意图

3程序设计

3.1系统功能

该软件具有多种功能,系统功能图如图3.1所示。

图3.1系统功能图

3.2主要函数介绍

3.2.1总体流程

程序的第一步是变量的初始化,定义了flag、time、sec等变量,并且设置了各个音调对应的十六进制码,然后开中断,对定时器进行模式的选择和初值的计算,接着调用LED显示函数使数码管按照程序设计的方式运行,其中扫描键盘是用定时器中断的方法,设置每隔3ms中断一次,即扫描一次键盘。

流程图如图3.2所示。

图3.2总体流程图

3.2.2数码管显示函数

数码管的显示在这里用的是动态显示方法,并且通过电路图得知,为了让74HC138芯片和74HC573芯片有效,计算出段控制口和位控制口分别为0x8004和0x8002。

流程图如图3.3所示。

图3.3数码管显示函数流程图

3.2.3键盘扫描

扫描键盘主要用的是unsignedcharGetKey()函数,而且还是用定时器中断的方法,设置每隔3毫秒中断一次,在一秒中大约会产生中断333次,就是说在一秒钟扫描键盘333次。

在扫描键盘的过程中,先是扫描哪一个的按键别按下,把第几列记录下来后,再扫描是哪一行的按键,记录是哪一行;最后根据公式“键值=列x4+行”,就能计算出是哪一个按键被按下。

如图3.4所示。

图3.4键盘扫描函数流程图

3.2.4计时函数

为了对歌曲进行计时,所以设计了一个计时函数jishi()。

分钟和秒钟分别用两个数码管来显示,当歌曲响起时开始计时,若秒钟个位加到10时,则十位加一,并且个位清零;秒钟的十位加到5时,分钟个位加一,并且将秒钟清零,分钟的十位同理,最后通过缓冲区在数码管中显示。

计时函数如图3.5所示。

图3.5计时函数流程图

3.2.5音乐函数

音乐函数song()是使蜂鸣器响起音乐的核心,一共有六首歌曲,分别用0x01——0x06控制着六首歌曲,通过用switch语句控制判断选择的是哪首歌曲,选择歌曲的序号后,调用相对应的并且储存了用十六进制数表示歌曲的数组,若在键盘中选择了1,就会调用tiger[],则蜂鸣器就会按照tiger数组中存储的十六进制码产生的频率响起音乐,播放结束后就会继续播放序号为2的歌曲。

如图3.6所示。

图3.6音乐函数流程图

4实验现象与问题

4.1操作说明与实验现象

“1”按键:

歌曲1,《两只老虎》

“2”按键:

歌曲2,《小青蛙》

“3”按键:

歌曲3,《千年之恋》

“4”按键:

歌曲4,《七子之歌》

“5”按键:

歌曲5,《找朋友》

“6”按键:

歌曲6,《寂寞沙洲岭》

“A”按键:

播放上一首歌曲

“B”按键:

播放下一首歌曲

“C”按键:

暂停键

数码管的第一位显示当前正在播放的歌曲序号,第三四位显示歌曲的分钟计时,第五六位显示歌曲的秒钟计时。

在键盘中选择“1”—“6”按键,就会播放相应的歌曲,六首歌曲循环播放,若当前播放的是第一首,选择“A”按键播放上一首歌曲就会播放第六首,若当前播放的是第六首,选择“B”按键播放下一首歌曲就会播放第一首,选择“C”按键时,歌曲和计时都会暂停,再按一次则继续播放音乐。

4.2问题与解决方法

问题1:

六个数码管中所有的段位都会发生很严重的闪烁现象,导致看不清数码管显示的数字,但运行的结果是正确的。

解决:

经过测试发现,试验箱连错了I/O口,连的是P3.7口,该口的功能是读写,改成连接P1.1口,闪烁消失。

问题2:

运行时数码管计数不稳定,有微弱的闪烁现象。

解决:

调整中断时间,将中断一次的时间3ms改成2ms,在1秒内产生500次中断,数码管变的更稳定。

问题3:

音乐跑调

解决:

音调的产生是根据声音产生的频率,再用公式计算出定时器的初值,计算错误导致音乐跑调。

 

参考文献

[1]张毅刚,刘杰.单片机原理与应用(第三版).哈尔滨:

哈尔滨工业大学出版社,2015.4.

[2]张仁彦,高正中,黄鹤松.单片机原理与应用.北京:

机械工业出版社,2016.3.

[3]付先成,,高恒强,蔡红娟.单片机原理与C语言程序设计.武汉:

华中科技大学出版社,2015.8.

[4]张校珩.单片机C语言编程100例.北京:

中国电力出版社,2014.1.

[5]唐颖.单片机综合设计实例与实验.北京:

电子工业出版社,2015.1.

附录(关键部分程序清单)

#include

#defineucharunsignedchar

#defineuintunsignedint

#defineLEDLen6

xdataunsignedcharOUTBIT_at_0x8002;//位控制口

xdataunsignedcharOUTSEG_at_0x8004;//段控制口

xdataunsignedcharIN_at_0x8001;//键盘读入口

unsignedcharLEDBuf[LEDLen];//显示缓冲

sbitfm=P1^1;//蜂鸣器

ucharu=0,num=0,num1=0;

uchartimeh,timel;

ucharmin0=0,min1=0,sec0=0,sec1=0;

ucharplay=0;

ucharflag1=0;

uintflag=0;

voiddelay1(uintz);//延时1ms

voiddelay(uintz);//延时165ms即十六分音符

voidsong();

//简谱音调对应的定时器初值适合11.0592M的晶振

ucharcodechuzhi[]={

0xff,0xff,//占位停顿

0xFC,0x8E,//中音1-7

0xFC,0xED,

0xFD,0x43,

0xFD,0x6A,

0xFD,0xB3,

0xFD,0xF3,

0xFE,0x2D,

0xFE,0x47,//高音1-7

0xFE,0x76,

0xFE,0xA1,

0xFE,0xC7,

0xFE,0xD9,

0xFE,0xF9,

0xFF,0x16};

codeunsignedcharLEDMAP[]={//八段管显示码

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71

};

ucharcodetiger[]={//两只老虎

0x14,0x24,0x34,0x14,0x14,0x24,0x34,0x14,

0x34,0x44,0x58,0x34,0x44,0x58,

0x52,0x61,0x52,0x41,0x34,0x14,0x52,0x61,0x52,0x41,0x34,0x14,

0x14,0xb4,0x18,0x14,0xb4,0x18,0xff,

};

ucharcodexqw[]={//小青蛙

0x52,0x32,0x32,0x32,0x52,0x32,0x32,0x32,0x54,0x61,0x52,0x32,0x42,0x24,

0x42,0x22,0x22,0x22,0x42,0x22,0x22,0x22,0x44,0x51,0x42,0x22,0x32,0x18,

};

ucharcodeqnzl[]={//千年之恋

0x12,0x22,0x34,0x84,0x74,0x54,0x38,0x42,0x32,0x22,0x42,0x34,0x84,0x72,0x82,0x94,0xA8,0x08,

0x32,0x31,0x21,0x32,0x52,0x32,0x31,0x21,0x32,0x62,

0x32,0x31,0x21,0x32,0x82,0x71,0x81,0x71,0x51,0x32,0x22,

0x32,0x31,0x21,0x32,0x52,0x32,0x31,0x21,0x32,0x62,

0x32,0x31,0x21,0x32,0x83,0x82,0x71,0x72,0x02,

0x63,0xA1,0xA2,0x62,0x92,0x82,0x52,

0x31,0x51,0x63,0x51,0x63,0x51,0x63,0x51,0x62,0x82,0x7C,0x02,

0x61,0x71,0x82,0x71,0x62,0xA2,0x71,0x76,

0x61,0x71,0x82,0x71,0x62,0x52,0x31,0x36,

0x61,0x71,0x82,0x71,0x62,0xA3,0x73,0x62,0x53,

0x42,0x63,0x83,0x83,0x91,0x91,

0x61,0x71,0x82,0x71,0x62,0x0A2,0x71,0x76,

0x61,0x71,0x82,0x71,0x62,0x52,0x31,0x36,

0x61,0x71,0x82,0x71,0x62,0xA3,0x73,0x62,0x53,

0x42,0x82,0x88,0x02,0x74,0x93,0x89,0xff

};

ucharcodeqizige[]={//七子之歌

0x54,0x32,0x52,0x32,0x54,

0x62,0x52,0x32,0x62,0x54,

0x14,0x12,0x22,0x34,0x52,0x32,

0x02,0x32,0x58,

0x52,0x52,0x62,0x52,0x32,0x54,0x52,0x62,0x52,0x82,0x62,0x58,

0x14,0x52,0x32,0x22,0x12,0x24,0x32,0x54,0x2,0x22,0x34,0x1f,0x18,

0x04,0x54,0xa4,0x92,0x81,0x62,0x52,0x54,0x62,0x64,0x52,0x62,0x81,0xa2,0x82,0x9c,

0x02,0x52,0xa4,0x92,0x81,0x62,0x52,0x54,

0x62,0x64,0x52,0x64,0xa2,0x92,0x9f,

0xa4,0x92,0x81,0x62,0x52,0x54,

0x84,0x62,0x52,0x32,0x22,0x14,

0x04,0x22,0x32,0x58,0x58,0x04,0x52,0x62,0x8f,0xff,

};

charcodezpy[]={//找朋友

0x14,0x14,0x14,0x24,0x34,0x54,0x58,0x54,0x64,0x54,0x34,0x24,0x34,0x24,

0x34,0x14,0x18,0x54,0x34,0x28,0x14,0x24,0x34,0x54,0x24,0x34,0x14,

};

ucharcodejmszl[]={//寂寞沙洲冷

0x12,0x12,0x22,0x32,0x31,0x22,0x21,0x22,

0x21,0x31,0x51,0x52,0x31,0x52,0x61,0x15,0x14,

0x51,0x52,0x31,0x52,0x62,0x13,0x11,0x13,0x32,0x28,0x08,0x28,

0x31,0x32,0x31,0x32,0x11,0x21,0x51,0x52,0x51,0x52,

0x51,0x51,0x31,0x32,0x31,0x32,0x81,0x72,0x63,

0x62,0x71,0x81,0x72,0x61,0x61,0x52,0x31,0x21,0x32,0x51,0x54,

0x22,0x12,0x11,0x12,0x11,0x12,0x12,0x14,0x26,0x32,0x26,

0x32,0x61,0x51,0x51,0x31,0x31,0x21,0x31,0x51,0x61,0x51,0x31,0x51,

0x02,0x32,0x81,0x81,0x81,0x81,0x62,0x52,0x34,0x31,0x81,0x81,0x81,0x61,0x91,0x82,

0x51,0x51,0x51,0x51,0x31,0x61,0x53,

0x21,0x11,0x21,0x11,0x22,0x11,0x21,0x26,

0x32,0x61,0x51,0x51,0x31,0x31,0x21,0x31,0x51,0x61,0x51,0x31,0x51,0x52,

0x31,0x31,0x81,0x81,0x81,0x61,0x91,0x81,0x61,0x31,0x56,

0x32,0x32,0x81,0x81,0x81,0x81,0x91,0x81,0x61,0x81,0x61,0x51,0x31,0x51,0x34,

0x21,0x31,0x51,0x31,0x21,0x11,0x61,0x21,0x16,

0xff};

voidInit()

{

LEDBuf[0]=0x00;

LEDBuf[1]=0x00;

LEDBuf[2]=0x3f;

LEDBuf[3]=0x3f;

LEDBuf[4]=0x3f;

LEDBuf[5]=0x3f;

}

voidDelay4(unsignedcharCNT)

{

unsignedchari;

while(CNT--!

=0)

for(i=100;i!

=0;i--);

}

voidDisplayLED()

{

unsignedchari;

unsignedcharPos;

unsignedcharLED;

Pos=0x20;//从左边开始显示

for(i=0;i

OUTBIT=0;//关所有八段管

LED=LEDBuf[i];

OUTSEG=LED;

OUTBIT=Pos;//显示一位八段管

Delay4

(1);

OUTSEG=0;

OUTBIT=0;

Pos>>=1;//显示下一位

}

OUTBIT=Pos;

OUTSEG=0;

OUTBIT=0;

}

codeunsignedcharKeyTable[]={//键码定义

0x16,0x15,0x14,0xff,

0x13,0x12,0x11,0x10,

0x0d,0x0c,0x0b,0x0a,

0x0e,0x03,0x06,0x09,

0x0f,0x02,0x05,0x08,

0x00,0x01,0x04,0x07

};

unsignedcharTestKey()//测试有没有按键

{

OUTBIT=0;//输出线置为0

return(~IN&0x0f);//读入键状态(高四位不用)

}

unsignedcharGetKey()//得到的是哪个按键

{

unsignedcharPos;

unsignedchari;

unsignedchark;

i=6;

Pos=0x20;//找出按键所在列

do{

OUTBIT=~Pos;

Pos>>=1;

k=~IN&0x0f;

}while((--i!

=0)&&

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2