乐曲程序的设计与实现.docx

上传人:b****6 文档编号:6681921 上传时间:2023-01-08 格式:DOCX 页数:21 大小:133.59KB
下载 相关 举报
乐曲程序的设计与实现.docx_第1页
第1页 / 共21页
乐曲程序的设计与实现.docx_第2页
第2页 / 共21页
乐曲程序的设计与实现.docx_第3页
第3页 / 共21页
乐曲程序的设计与实现.docx_第4页
第4页 / 共21页
乐曲程序的设计与实现.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

乐曲程序的设计与实现.docx

《乐曲程序的设计与实现.docx》由会员分享,可在线阅读,更多相关《乐曲程序的设计与实现.docx(21页珍藏版)》请在冰豆网上搜索。

乐曲程序的设计与实现.docx

乐曲程序的设计与实现

课程名称

汇编语言程序设计

题目

乐曲程序的设计与实现

课程设计任务书1

1实验内容、目的1

1.1实验内容1

1.2实验目的1

2设计中使用的关键技术及方法…………………………………………………………2

2.1位触发方式……………………………………………………………………………2

2.2利用定时器产生声音…………………………………………………………………..3

2.3扬声器驱动方式………………………………………………………………4

2.4主要的发生器件………………………………………………………………5

2.5乐曲构成………………………………………………………………………6

3设计方案说明……………………………………………………………………………6

3.1设计思路………………………………………………………………………6

3.2程序流程图…………………………………………………………………7

3.3关键代码设计实现及分析……………………………………………………8

4调试过程及实验结果分析………………………………………………………………11

4.1调试过程……………………………………………………………………11

4.2实验结果……………………………………………………………………12

5设计心得与改进方案…………………………………………………………………13

5.1心得体会……………………………………………………………………13

5.2改进方案……………………………………………………………………13

6参考文献…………………………………………………………………………………14

7附录源程序……………………………………………………………………………14

本科生课程设计成绩评定表……………………………………………………………18

课程设计任务书

 

学生姓名:

专业班级:

指导教师:

工作单位:

计算机科学与技术学院

题目:

乐曲程序的设计与实现

初始条件:

理论:

完成了《汇编语言程序设计》课程,对微机系统结构和80系列指令系统有了较深入的理解,已掌握了汇编语言程序设计的基本方法和技巧。

实践:

完成了《汇编语言程序设计》的4个实验,熟悉了汇编语言程序的设计环境并掌握了汇编语言程序的调试方法。

要求完成的主要任务:

(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)

进一步理解和掌握程序直接控制I/O方式,掌握计算机发声程序的设计。

具体的设计任务及要求:

1.采用位触发方式编写程序,使计算机发出音响并演奏乐曲(例如《两只老虎》等)。

1)进一步理解程序直接控制I/O方式和位触发方式控制声音的工作原理。

2)一首乐曲是由不同频率和节拍的音调组成,因此控制脉冲的频率和持续时间是编写乐曲程序的关键。

根据已知的音符频率对照表,设置乐曲的频率表和节拍时间表;

3)编写程序并调试通过。

2.了解定时器的工作原理,掌握利用定时器产生声音的方法,使计算机演奏乐曲(例如《两只老虎》等)。

编写程序并调试通过。

在完成设计任务后,按要求撰写课程设计说明书;对课程设计说明书的具体要求请见课程设计指导书。

阅读资料:

1)《IBM—PC汇编语言程序设计实验教程》3.1节

2)《IBM—PC汇编语言程序设计(第2版)》10.4节,10.5节

时间安排:

设计安排一周:

周1、周2:

完成系统分析及设计。

周3、周4:

完成程序调试,和验收。

周5:

撰写课程设计报告。

 

指导教师签名:

年月日

系主任(或责任教师)签名:

年月日

乐曲程序的设计与实现

1.实验内容、目的

1.1实验内容

1.进一步理解和掌握程序直接控制I/O方式,掌握计算机发声程序的设计。

具体的设计任务及要求:

1)进一步理解程序直接控制I/O方式和位触发方式控制声音的工作原理。

2)一首乐曲是由不同频率和节拍的音调组成,因此控制脉冲的频率和持续时间是编写乐曲程序的关键。

根据已知的音符频率对照表,设置乐曲的频率表和节拍时间表;

3)编写程序并调试通过。

2.了解定时器的工作原理,掌握利用定时器产生声音的方法,使计算机演奏乐曲(例如《两只老虎》等)。

编写程序并调试通过。

1.2实验目的

汇编语言是计算机能够提供给用户使用的最快而又有效的语言,也是能够用计算机所有硬件特性并能直接控制硬件的唯一语言。

通过这次实验要求我们:

1)了解通用发生程序。

2)了解与掌握定时、计数、音乐、频率、时间之间的关系。

3)学会用发生程序的设计方法

4)学会用汇编语言编辑音乐程序

通过音乐程序设计熟悉并掌握用汇编语言编程的方法和特点,借此来比较高级语言低级语言的优缺点,以便更好运用各种语言来开发应用软件通过实际动手能力的培养,进一步熟悉汇编语言的结构和使用方法,达到能独立阅读、编制和调试一定规模的汇编语言程序的水平。

能用汇编语言熟练的运用三大结构,进一步掌握各个指令的功能,特别是转向指令,能掌握子程序的定义及调用,包括段间及段内调用,以及正确的运用DEBUG指令,进一步理解和掌握程序直接控制I/O方式。

2.设计中使用的关键技术及方法

ROMBIOS中有个BEEP子程序,这能根据BL中组出的时间计数值控制8254定时器,产生持续时间为1个或几个0.5秒,频率为896HZ的声音,我们可以利用并修改BEEP,使其产生任一频率的声音。

为此我们需要做两点修改,首先,BEEP程序只能产生896HZ的声音,我们的通用发声程序应能产生任一频率的声音。

其次,BEEP产生声音的持续时间(音长)只能是0.5秒的倍数,我们希望声音的持续时间更易于调整,例如可以是10ms的倍数。

我们知道BEEP能将计数值533H送给定时器2产生896HZ的声音的,那么产生其它频率声音的时间计数值应为:

533H×896÷给定频率=123280H÷给定频率

发声程序包括3个步骤:

(1)在8253中的42端口送一个控制字0B6H(10110110B),该控制字对定时器2进行初始化,使定时器2准备接收计数初值。

(2)在8253中的42H端口(Timer2)装入一个16位的计数值(533H×895/频率),以建立将要产生的声音频率。

(3)把输出端口61H的PB0、PB1两位置1,发出声音。

2.1位触发方式

程序直接控制PPI(8255A可编程序外围接口芯片)的输出控制器(I/O端口为61H)的第一位,使该位按所需的频率进行1和0的交替变化,从而控制开关电路产生一串脉冲波形,这些脉冲波形经放大后驱动扬声器发出声音。

如果控制波形的脉宽和长度就可以产生不同频率和不同音长的声音。

扬声器发声通用子程序:

通用发生程序CFSOUND:

cfsoundprocnear

pushdx保存将要用到的寄存器

pushax

inal,61h

movah,al

andal.11111100b关断定时器通道2的门控

sound:

xoral,2触发61h端口第一位

out61h,al

movax,2801

movbx,50

mulbx

divcx(cx)=freq

movdx,ax

movcx,dx(dx)=控制脉宽的计数值

wait:

loopwait延时循环

movax,8

mulbx

movbx,ax(bx)=扩大8倍的节拍计数器

decbx(bx)=脉冲持续的时间

jnzsound

popax恢复寄存器

popdx

moval,ah写回61H口原值,关闭扬声

out61h,al

ret子程序结束返回

cfsoundendp

2.2利用定时器产生声音

利用机器硬件即INTEL8253/8254定时器产生声音的一种方法。

CPU通过对定时器的通道2(端口地址为42H)进行编程,使其I/O寄存器接收一个控制声音频率的16位计数值,端口61H的最低位控制通道2门控的开断,以产生特殊的音响。

当定时器接收的计数值为533H时,能产生896Hz的声音,因此产生其他频率(Freq)的计数值就可由下式计算出来:

533H*896/Freq=1234DCH/Freq

在送出频率计数值之前,还要给方式寄存器(端口其值为43H)送一个方式值,也称为幻数。

这个幻数由8为组成即D7,D6,D5,D4,D3,D2,D1,D0选择计数值的格式,1为BCD码格式,0为二进制格式。

D3,D2,D1选择操作模式,它决定了输出脉冲的形状。

D5,D4读写指示位。

D7,D6选择计数器,确定控制字是对哪一个计数器进行初始化。

利用定时器产生制定频率声音的程序段:

Moval,10110110b为组合格式:

通道2,两字节技术,模式3,二进制码

Out43h,al幻数送方式寄存器

Movdx,12h

Movax,34dch

Divdi(di)=Freq

Out42h,al频率计数值送通道2

Moval,ah

Out42h,al

控制音长的时间可以简单的通过反复执行循环指令来得到。

我们已执行2810次LOOP指令约需要10ms时间,因此使用10ms的倍数值来控制扬声器开关的时间间隔,就可以控制音长。

具体实现的指令序列如下:

Inal,61h

Movah,al

Oral,3

Out61h,al接通扬声器

Leng:

movcx,280110ms音长的计数器

Delay:

loopdelay

Decbx(bx)=10ms的倍数值

Jnzleng

Moval,ah

Out61h,al关闭扬声器

2.3扬声器驱动方式

PC机上的大多数I/O都是由主办上的8255可编程序外围接口芯片PPI管理的。

PPI包括三个8位寄存器,两个用于输入功能,一个用于输出功能。

输入寄存器分配的I/O端口号为60H和62H,输出寄存器分配的I/O端口号为61H。

由PPI输出寄存器中的0和1两位来控制扬声器的驱动方式。

连接到扬声器上的是定时器2.GATE2与端口61H的PBO相连,当PBO=1时,GATE2获得高电平,是定时器2可以在模式3下工作。

定时器2的OUT2与端口61H的PBI通过一个与门与扬声器的驱动电路相连。

当PBI=1时,允许OUT2的输出信号到达扬声器电路。

控制扬声器的代码:

Inal,16h

Movah,al

Oral,00000011b

Out61h,al

……………

Moval,ah

Out61h,al

2.4主要的发生器件(可编程时间间隔定时器8251/54)

在8253/54定时器内部有3个独立工作的计数器:

counter0,counter1,counter2,个计数器都分配有一个端口地址,分别为40H,41H和42H。

8253/54内部还有一个公用的控制寄存器,端口地址为43H。

端口地址输入到8253/54的CS,AL,AO端,分别对3个计数器和控制器寻址。

如图下图所示:

8253/54定时器结构图

对8253/54编程时,先要设定控制字,来选择计数器,确定工作模式和计数值的格式。

每个计数器由3个引腿和外部联系。

CLK为时钟输入端,GATE为门控信号输入端,OUT为技术/定时信号输出端。

每个计数器中包含一个16位的计数寄存器,这个计数器是以倒计数的方式计数的,也就是说,从计数初值开始逐次减1,直到减为0为止。

同时8253/54三个计数器是分别编程的,对任一个计数器编程时,必须首先将控制字写入控制寄存器。

控制字的作用是确定需要使用的计数器,同时确定要求输出的脉冲波形。

另外,对8253/54的初始化工作还包括,向选定的计数器送入一个计数初值,因为这个计数值可以是8位的,也可以是16位的,而8253/54的数据总线是8位的,所以要用两条输出指令来写入初值。

控制字节由8位组成即D7,D6,D5,D4,D3,D2,D1,D0选择计数值的格式,1为BCD码格式,0为二进制格式。

D3,D2,D1选择操作模式,它决定了输出脉冲的形状。

D5,D4读写指示位。

D7,D6选择计数器,确定控制字是对哪一个计数器进行初始化。

对8253/54设置初始值时,一定要符合控制的格式规定,是二进制数还是BCD码表示的数,是只写高(低)字节,还是高低字节都写。

控制字一旦做出决定,程序中给出的计数值就要和控制的要求一致。

2.5乐曲构成

由于把很多发生程序“结合”就构成理论上的曲子,所以利用计算机控制发生的原理,可以编写演奏乐曲的音调。

在一首乐曲中,每个音符的音高和音场与频率和节拍有关。

组成乐曲的每个音符的频率值和持续时间是乐曲程序发声所需要的两个数据。

音符的持续时间是根据乐曲的速度及每个音符的节拍数来确定。

在4/4(四四拍)中,四分音符为1拍,每小节4拍,全音符持续4拍,二分音符持续2拍,四分音符持续1拍,八分音符持续半拍等。

如果给全音符的持续时间为0.25s(25*10ms),八分音符的持续时间为0.125(12.5*10ms).

音符的频率参考下表编写:

1

2

3

4

5

6

7

低音

131

147

165

175

196

220

247

中音

262

294

330

349

392

220

494

高音

524

588

660

698

784

880

984

3.设计方案说明

3.1设计思路

编写这个乐曲程序可分为四个步骤:

1)定义频率表和时间表

根据音阶表和简谱为演奏的乐曲定义一个频率表FREQ和一个节拍时间表TIME.

2)将两个表的偏移地址放入SI和DI

LEASI,MUS_FREQ

LEABP,DS:

MUS_TIME

3)取频率和时间

MOVDI,{SI}

MOVBX,DS:

{BP}

4)调用SOUND子程序发出音调

3.2程序流程图

主程序流程图

说明:

在进入主界面的时候有6个选项,分别是

1:

MUSIC1--MERRYCHRISTMAS

2:

MUSIC2–TAIHU

3:

MUSIC3--LITTLEBEE

4:

PLAYBYKEYBOARD

5:

PRESS5TOQUIT

6:

CLEARTHESCREEN

通过选择不同的选项进入其子界面来实现不同的功能。

3.3关键代码设计实现及分析

3.3.1程序段说明

1)DATAS为数据段,其中存放在程序中所要显示的提示选择信息,还有乐曲的频率表和节拍表,和键盘控制发声对应的音符表。

2)CODES为代码段,由于在整个程序中各个子程序都定义为NEAR,所以只需要有一个代码段,各个子程序的定义及实现都放在其中。

3.3.2PLAY_MUSIC乐曲演奏程序的实现及分析

“PLAY_MUSIC”为播放音乐的子程序,完成的功能是通过SI(频率表的偏移地址)BP(节拍表的偏移地址)(通过主程序传递过来的参数)找到对应的频率(DI)、节拍(BX),再以DI、BX为参数调用SOUNDF子程序来发出声音。

关键代码:

FREQ:

MOVDI,[SI]

CMPDI,0

JEEND_MUSIC

MOVBX,DS:

[BP]

CALLSOUNDF;以DI(频率)BX(节拍)为参数,调用SOUNDF

ADDSI,2

ADDBP,2

JMPFREQ

SI,BP是频率表和节拍表的偏移地址,通过寄存器间接寻址方式找到数据段中定义

数据,传递给BX和DI,然后调用SOUNDF发出一个频率为DI,节拍数为BX的声音注意:

在频率表中应该设置一个结束标志,“CMPDI,0”,在这里以0作为结束标志。

3.3.3SOUNDF通用发声程序的实现及分析

SOUNDF”为以传递过来的频率和节拍数,发出一个音符的频率的子程序。

关键代码分析:

MOVAL,0B6H

OUT43H,AL

置43H端口为0B6H,选择计数器2,读/写LSB,MSB,模式3,计数值为二进制数。

MOVDX,12H

MOVAX,348CH

DIVDI

按照公式,计数值=12348CH÷f,商存放在AX中。

OUT42H,AL

MOVAL,AH

OUT42H,AL

8253\54的数据总线为8位,而计数值为16位,所以应该分两次传递计数值。

INAL,61H

MOVAH,AL

ORAL,3

OUT61H,AL

将61H的后两位置1,打开扬声器,使其发声。

WAIT1:

CALLWAITF

DECBX

JNZWAIT1

用WAITF产生一个10ms的延时,BX是节拍(10ms的倍数)。

MOVAL,AH

OUT61H,AL

恢复寄存器状态

3.3.4WAITF延迟程序的实现及分析

“WAITF”为通过监控端口61H的PB4固定不变的触发时间来产生延迟时间的子程序。

关键代码分析:

MOVCX,663

WAITF1:

INAL,61H

ANDAL,10H;查看61H寄存器的第四位(PB4)

CMPAL,AH

JEWAITF;PB4每15.08秒触发一次

MOVAH,AL;

LOOPWAITF1

10ms/15.08us=663,所以先置CX为663,每次通过调用WAITF都会产生一个

10ms的延迟。

3.3.5KEYBOARD键盘发声程序的实现及分析

“KEYBOARD”子程序,通过按不同的按键(1~8)来产生不同频率的音符。

关键代码分析:

PLAY_BY_KB:

MOVAH,7

INT21H

CMPAL,0DH

JEQT

MOVBX,OFFSETTABLE

CMPAL,'1'

JBPLAY_BY_KB

CMPAL,'8'

JAPLAY_BY_KB

输入按键,回车退出,如果不是1~8的话跳转到开始重新输入。

ANDAX,0FH;清空AH

SHLAX,1

SUBAX,2

找到索引地址,是DW型的,所以需要乘2,而且是从0开始,应该减去2

MOVSI,AX

MOVDI,[BX][SI]

MOVBX,10

CALLSOUNDF

通过索引从符号表里面找到对应的频率,调用SOUNDF发出声音。

4、调试过程及实验结果分析

4.1调试过程

1:

在刚开始显示字符串的时候,应该加上0DH,0AH换行,而且在字符串的最后应该以"$"来结尾,然后调用DOS调用INT21H,来显示字符串。

调试中发现,如果一个字符串末尾不加"$"的话,DOS调用会直接把之后定义的字符串也同时显示出来,直到遇到"$"为止。

这是由内存的分配模式所决定的,同时定义的变量在内存中会处于相邻位置。

2:

在调试子程序KEYBOARD的时候,发现管输入‘0’程序不会返回,是因为在程序中直接CMPAL,0。

而从键盘输入的是ASC码,‘0’对应的ASC码为30H,所以修改语句如下:

CMPAL,'0'。

3:

在调试KEYBOARD的时候,发现输入1~8只有7会发出声音,检查后发现由于在TABLE表中定义的是DW字,而在程序中直接将输入符号作为索引值,应该将输入数字减一乘二才能得到正确的索引值。

4:

在调用CLEAR的时候,发现每次显示的列表都会向下移动。

在清除前应该将光标位置移动到第0行,第0列。

5:

在输入字符较多的情况下,界面显得较为凌乱,所以在程序中添加了一个清屏子程序,每次在返回选择界面的情况下清屏,但是在调试过程中,每当调用CLEAR的时候就出现错误:

“C:

\WINDDOWS\system32\cmd.exeNTVDMCPU遇到无效的指令CS:

01e7IP:

018bOP:

dbfe06cd02”,查阅资料,发现是软件兼容问题。

最后查阅书本,发现如果要实现清屏功能的话应该先把光标的位置定位到界面的开始位置(行、列号都为0),然后参照书本P330的例9.11来实现清屏功能。

6:

刚开始时候,直接把延迟时间(15.08us)通过CX寄存器传递给子程序WAITF,这样会导致每次传递的时候都应该计算。

所以之后在WAITF中直接将CX初始化为663(10ms/15.08us=663),每次调用WAITF就能产生10ms的延迟,但要特别注意的是,如果WAITF中用到CX,首先应该将CX压栈(PUSHCX),返回之前出栈(POPCX)。

7:

结果显示界面显得比较单调,为了增加程序美观性,定义了一个利用BIOS功能调用来设置显示方式和背景色。

但要特别注意的是调用的时机,应该在每次刷新并且显示选择列表之前调用。

4.2实验结果

这是进入程序页面后的屏幕显示,通过y和n来播放音乐或者结束

 

图表4播放音乐界面

程序正在播放歌曲。

 

上面是两只老虎的简谱,可以结合这个来听音高低。

结果如上所示

5、设计心得与改进方案

5.1心得体会

在程序中,各个变量及标号应该有统一且明确的命名规范,例如频率表的命名规则为:

“歌曲名_F“,节拍表的命名规则为:

“歌曲名_T“这样能使代码的可读性大大增强,且在编程中也能使逻辑更加清晰,增加编程效率。

不能一开始就开始编写程序,而是应该首先分析问题,设计出程序的框架流程图,明确各个程序段的功能,这样能使效率提高并且能增强持续的逻辑性和可读性,也可以避免出现很多错误

在设计中应该考虑全面,并且兼顾到各方面的问题。

不能仅仅完成布置的任务,应该努力使程序更健壮,能够处理错误的输入并且给出提示,而且应该有更强的交互能力。

在做课程设计的过程中难免会出现这样那样的问题,因此要保持良好的心态,在遇到问题时应该仔细想问题的起因及解决方法,不能想都不想就直接放弃或者问人,这样就失去了做报告的意义,因为在解决问题的过程中可以发现很多以前忽视的问题。

发现问题,解决问题是我们的主要目的。

这次的课程设计让我有机会通过实践来加强、巩固学习过的知识,极大的增强了自己编程能力。

5.2改进方案

1.刚开始设计流程图的时候,可以直接将内置的2首音乐分别定义一个子程序来演奏,在之后的编程过程中,发现这样的设计不合理且会使代码变的更长且冗余,然后改进设计,以一个SOUNDF子程序来演奏音乐,调用SOUNDF的时候直接将需要演奏的频率表和节拍表作为参数传递给SOUNDF程序,这样能使代码更简洁,可读性大大增强。

2.如果需要播放其他音乐时,只要在数据段增加此音乐的频率表和节拍表,然后在选择项中添加一个选项即可。

3.在调用子程序的过程中,应该注意保存寄存器中的内容,避免在子程序中破坏其中的数据。

可以考虑使用主界面的方式,多插入几首歌曲,增加程序的选择性,使不至于单一。

可以通过自己设计的利用系统定时器的中断程序来实现控制发声时间长短的功能,使程序的发声时间有一个具体的时间基准。

在系统定时器的中断处理程序中,有一条中断指令INT1CH,时钟中断每发生一次(约每秒中断18

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

当前位置:首页 > PPT模板 > 动态背景

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1