音乐播放程序设计.docx
《音乐播放程序设计.docx》由会员分享,可在线阅读,更多相关《音乐播放程序设计.docx(23页珍藏版)》请在冰豆网上搜索。
音乐播放程序设计
引言
大学生动手能力的培养和提高一直是教育工作者探索的课题,《微机原理与接口技术》就是一门实用性很强的课程。
如何让学生在学好基础知识的同时,迅速掌握设计应用技术,其中实验与课程设计环节起着非常重要的作用。
通过此次课程设计,使学生能够较全面地巩固和应用课堂中所学的基本理论和程序设计方法,能够较熟练地完成汇编语言程序的设计和调试。
培养学生勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位考虑问题等科学技术人员应具有的素质。
众所周知,随着科学技术的迅猛发展,计算机在各个领域的应用越来越广泛。
计算机已成为人们生活、学习、工作中必备的工具。
其中,汇编语言是计算机能够提供给用户使用的最快而有效的语言,也是能够利用计算机所有特性并能直接控制硬件的唯一语言。
借助于汇编程序,计算机本身可以自动地把汇编源程序翻译成用机器语言表示的目的程序,从而实现了程序设计工作的部分自动化。
本次课程设计的过程重视基础、系统性和使用性相结合,以80X86处理器为对象,以8253/8254为计数器的核心,通过宏指令和BOIS系统功能的调用,以及运用MASM软件在PC机上来进行调试和运行,从而模拟地来实现“音乐演奏”的目的。
音乐播放程序设计
1总体要求与分析
1.1设计要求
本文采用汇编语言设计一个播放音乐程序,,该程序可以进行如下操作:
按大写字母“A”,奏一首歌曲;按大写字母“B”;奏另一首歌曲,曲目自选。
按Q退出程序。
1.2设计思路分析
在IBM-PC/XT机中都带有8253-5定时/计数器,IBM-PC/AT中带有8254定时/计数器,这两种芯片功能十分类似。
本文通过对8253-5定时/计数器芯片的操作实现音乐演奏。
该声音接口通过汇编语言对8253-5的端口直接进行操作,可以不必要过多的使用BIOS的调用和DOS的调用。
计数器芯片有3个通道,各自具有专用功能。
通道0时系统的始终节拍计时器,通道1专用于产生动态RAM的定时刷新信号,通道2用来控制计算机的扬声器的声音频率。
该音乐演奏主要用到通道2的功能,使通道2工作在“方波发生器”方式,产生相应频率的音调送至喇叭驱动电路,使喇叭发出不同音调的声音。
使用8255A的PB0控制通道2的计数,PB1控制通道2的输出对扬声器产生控制的时间。
人机交互包括屏幕显示提示语以及人工输入相应参数,主要应用到BIOS的10H号中断调用以及DOS的21H号中断调用。
BIOS的10H号中断调用用于显示器驱动,设置显示模式和光标位置;DOS的21H号中断调用用于单字符输入以及多字符输出显示。
音乐演奏实现的一个主要步骤是乐谱编程。
通过相应的频率表将乐谱中对应的音符转化为计数器的计数初值,节奏通过延时程序转化为对喇叭发音时间的控制,从而实现音符和节拍的数字化。
2方案设计
音乐的实现主要是对乐谱中的单音符按照一定的音符频率表转化为计数器的计数频率以及喇叭发声的控制时间,通过计数产生相应的控制动作。
利用硬件实现频率计数和延时时间的控制,利用8253-5定时/计数器芯片和8255A并行I/O接口芯片。
使8253的一个通道工作在“方波发生器”模式,实现对频率的计数;利用8255A的PB3端口实现发声时间的计数控制。
这样可以精确的控制时间,减少CPU的开支。
3硬件电路
IBM-PC/XT内部8253电路图如图1所示。
图18253电路连接图
8253的通道0用于产生固定频率的始终节拍,通道1用于产生固定频率的的刷新信号,通道2用于产生频率信号,工作在方式3,计数值为6A4H=1190,方波输出频率为1.19MHZ。
此信号频率决定扬声器的音调,通道2的控制字为0B6H。
音乐产生主要用到通道2。
8253通道2的计数由8255A的PB0控制,当PB0输出为高电平时,使门控GATE2为高电平。
此时,8253通道2允许计数,故通道2的输出方波受PB0的控制,从而控制扬声器的音调高低。
通道2的输出能否对扬声器产生持续控制还取决于8255A的PB1。
当PB1为“0”时,OUT2不能通过“与门”;反之,则可以通过“与门”控制扬声器。
所以,扬声器发音时间的长短取决于8255A的PB1信号。
另外CPU通过读8255A的C口,得知8253通道2的状态和扬声器驱动器的状态。
4软件设计
4.1屏幕显示设计
程序运行时,屏幕显示第一界面如下:
MusicPlayer
PleaseSelectaSong
ATwoTigers
BZhengfu
QExit
----------------------
选择A、B分别演奏相应的音乐,选择Q键结束程序运行。
当输入别的按键信号时,显示出错提示信息,界面如下:
ERROR!
!
!
ChooseABQ
PleaseInputAgain!
MusicPlayer
PleaseSelectaSong
ATwoTigers
BZhengfu
QExit
----------------------
按照提示信息重新输入正确字符即可。
上述提示信息在数据段定义,类型为字节型。
首先调用BIOS中断的10H号功能设置文本模式。
程序如下:
MOVAH,00H;BIOS10子功能
MOVAL,02H;80*25彩色文本模式
INT10H;BIOS10功能调用
然后调用背景清屏子程序使文本屏幕清空,为输入信息作准备,清屏子程序如下:
CLRPROCNEAR
MOVBH,0;第0页
MOVBL,00011010B;字符属性,蓝底绿字不闪烁
MOVDX,0000H;0行0列
MOVAL,'';输出的字符
MOVCX,80*25;循环次数
MOVAH,02H;BIOS10H子功能调用,置光标位置
INT10H
MOVAH,09H;BIOS10H子功能调用,输出字符
INT10H
RET
CLRENDP
最后输出提示语字符。
输出提示语字符时,需要多次使用一段相同的输出代码,将该代码定义为宏,可以避免多次重复书写相同的代码。
不定义为子程序是为了避免多次调用使执行速度减慢。
相应宏定义语句为:
SHOWMACROb
LEADX,b;将相应字符段的偏移地址装入DX
MOVAH,9;DOS21H号中断9子功能输出多字符
INT21H
ENDM
则相应的字符提示信息输出代码为:
CALLCLR
showINFO1
showINFO2
showINFO3
showINFO4
showMUSLIST
4.2音乐发声控制
一首乐曲由若干音符组成,一个音符对应一个频率。
将与一个频率对应的计数器初值写入2号计数器(端口地址为42H),扬声器就发出相应的音调,计数器初值的计算公式:
计数器初值=1193182/输出频率
其中,1193182Hz转换成十六进制为12348CH,因此在打开扬声器的条件下,执行下列程序段即可发出与输出频率对应的音调。
MOVAL,0B6H;写入方式控制字
OUT43H,AL;写入控制端口
MOVDX,12H
MOVAX,348CH
DIV频率值 ;频率转换成计数初值
OUT42H,AL ;低8位送2号计数器
MOVAL,AH
OUT42H,AL ;高位送2号计数器
接下来设计发声程序,发声系统受8255A芯片(端口地址为60H-63H)的两根输出线PB0和PB1的控制,PB0输出的高电平使2号计数器正常工作,PB1输出高电平打开输出控制门。
发声程序代码如下:
INAL,61H;读取8255A的PB端口原输出值
MOVAH,AL;将原输出值保存于AH中
ORAL,3;使PB0、PB1、均为1
OUT61H,AL;打开GATE2门,输出方波到扬声器
4.3节拍时间的实现
下面控制音符的演奏时间,这是设计音乐程序的关键问题。
最直观的方法是按照谱为每一个音符规定一个演奏时间。
在遇到一首不熟悉歌曲时,初期很难确定每个音符的演唱时间,而调试程序的需大量的时间。
为每一个音符规定“单位时间”:
单位时间*N=音符的延长时间
其中,N为调试参数,一首歌曲只有一个调试参数。
设计程序时可以用EQU伪指令定义调试参数,初值现行估算,调试时在修改它。
节拍时间设置好以后,就可以利用延时程序,通过PB1端口控制发声的时间长短。
80x86的各种处理器采用6-66MHZ的工作频率,LOOP治理的执行时间在这些处理器上也不同。
为了建立一个与处理器无关的时间延迟,IBM采用了一个利用硬件产生时间延迟的方法,即通过监控端口61H的PB4,使PB4每15.08us触发一次,以产生一个固定不变的时间基准,在IBM-PC/XT中的BIOS中的WAITF子程序,就是一个产生N*15.08us时间延迟的程序,调用WAITF子程序时,CX寄存器必须装入15.08us的倍数N。
本程序延时程序参考上面的原理,代码如下:
waitfprocnear;延时保护程序
pushax;保护寄存器
waitf1:
inal,61h;读取PB端口地址
andal,10h;低四位清零
cmpal,ah;检查是否改变
jewaitf1;等待改变
movah,al;改变,保护新端口值
loopwaitf1;继续,直到CX=0
popax;恢复寄存器
ret
waitfendp
4.4音乐乐谱编程
组成音乐的每个音符的频率值和持续时间是音乐程序发声所需要的两个数据,根据音调与频率和时间之间的关系,把要编辑的音乐的每个音符的频率和持续时间定义成两个数据表,进而把它们写入通用发声程序。
音符频率表示见表1所示,编程产生各种音符的频率时可参照此表。
表1音符频率表(单位:
赫兹)
4.5程序流程图
主程序流程图如图2。
Y
N
Y
N
Y
N
图2主流程图
MUSIC子程序流程图如图3。
Y
N
图3MUSIC子程序流程图
GENSOUND子程序流程图如图4所示:
N
Y
图4GENSOUND子程序流程图
5程序调试及运行
把编好的源程序命名保存为YINYUE.asm,在asm集成环境中进行调试,检查错误并逐一改正,直至编译无错误,如果编译成功,就选择运行选项中的生成exe文件,这样就生成了一个可运行程序。
调试过程中会遇到一些问题,比如界面出现错误,如图5所示。
图5运行错误界面
对于上面出现的错误,要在主菜单的数据段定于语句中字符串后面加了'$',问题就可以得到解决。
运行结果演示过程见附录2。
6小结与体会
本文编写的音乐演奏程序可以满足设计要求,能够播放音乐,并且能够有屏幕显示,极大地方便了人机交互。
这次微机原理课程设计历时两个星期,在整整两星期的日子里,不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
在这次的课程设计中,对于汇编语言的各种功能终于有了一个比较全面和具体的认识,在亲自动手编写程序的过程中,发现了很多读程序时不能发现的漏洞。
虽然上课学过很多的理论,平时也看了一些辅导书上的程序,但是真正自己动手才发现以前对于编程工具的使用还处于一知半解的状态上,各种指令和伪指令代码间的联系还不会应用,这次经过一段上机的实践,对于怎么去排错、查错,怎么去看每一步的运行结果,怎么去了解每个寄存器的内容以确保程序的正确性上都有了很大程度的提高。
在这次课程设计中,把以前学的支离破碎的指令代码相互的功能结合起来,使它们共同组成一个具有一定功能的小程序,这样大大提高了对于汇编语言的功能的认识,同时也极大地提高了我的兴趣。
通过这次课程设计使我更加体会到了理论与实际相结合的重要性,只有理论知识是远远不够的,在实践中可能会遇到各种各样的问题,不多经历就无法感受到这一点。
要在实践中提高自己的动手能力和解决问题的能力,从而学以致用。
附录
附录1程序源代码
DATASEGMENT
INFO1DB0DH,0AH,'MusicPlayer$'
INFO2DB0DH,0AH,'$'
INFO3DB0DH,0AH,'PleaseSelectaSong$'
INFO4DB0DH,0AH,'$'
INFO5DB0DH,0AH,'ERROR!
!
!
ChooseABQ$'
INFO6DB0DH,0AH,'PleaseInputAgain!
$'
MUSLISTDB0DH,0AH,'ATwoTigers'
DB0DH,0AH,'BZhengfu'
DB0DH,0AH,'QExit'
DB0DH,0AH,'-------------------------'
DB0DH,0AH,'$'
;*********************************************两只老虎
MUS_FREG1DW262,294,330,262
DW262,294,330,262
DW330,350,393
DW330,350,393
DW393,441,393,350,330,262
DW393,441,393,350,330,262
DW294,196,262
DW294,196,262,-1
MUS_TIME1DW4*15,4*15,4*15,4*15
DW4*15,4*15,4*15,4*15
DW4*15,4*15,8*15
DW4*15,4*15,8*15
DW2*15,1*15,2*15,1*15,4*15,4*15
DW2*15,1*15,2*15,1*15,4*15,4*15
DW4*15,4*15,8*15
DW4*15,4*15,8*15
;*********************************************征服
MUS_FREG2DW784,1046,988,784,880,659,880
DW880,880,880,784,659,659,698
DW698,698,698,784,880,659,698,587
DW784,1046,988,784,784,880,784
DW784,1046,988,784,880,659,880
DW880,880,880,784,659,659,698
DW698,698,698,659,523,523,587,523,-1
MUS_TIME2DW50,100,50,50,100,50,250
DW50,100,50,50,100,50,250
DW50,50,100,50,100,50,250
DW50,50,100,50,50,200,50,250
DW50,100,50,50,100,50,250
DW50,100,50,50,100,50,250
DW50,50,100,50,100,50,300
DW50,50,100,4DUP(50),200
;*********************************************
DATAENDS
STACKSEGMENT
DB200DUP('STACK')
STACKENDS
CODESEGMENT
ASSUMEDS:
DATA,SS:
STACK,CS:
CODE
MAIN:
MOVAX,DATA
MOVDS,AX
MOVAH,00H;BIOS10子功能
MOVAL,02H;80*25彩色文本模式
INT10H;BIOS10功能调用
CALLCLR
;*********************************************定义宏
SHOWMACROb
LEADX,b;将提示语的偏移地址送入DX
MOVAH,9;调用中断,输出多字符
INT21H
ENDM
;*********************************************音乐地址宏
ADDRESSMACROA,B
LEASI,A;将频率表的偏移地址送入SI
LEABP,DS:
B;将节拍时间表的偏移地址送入BP
ENDM
;******
showINFO1
showINFO2
showINFO3
showINFO4
showMUSLIST
INPUT:
MOVAH,01H;等待输入一个字符
INT21H
CMPAL,'Q';比较字符
JZretu;是,返回
CMPAL,'A';与A比较
JNZB0;不等再比较
ADDRESSMUS_FREG1,MUS_TIME1;取数据
CALLMUSIC;调用音乐子程序
JMPEXIT1
B0:
CMPAL,'B'
JNZexit
ADDRESSMUS_FREG2,MUS_TIME2
CALLMUSIC
EXIT1:
JMPINPUT;继续等待输入
EXIT:
MOVAH,00H;BIOS10子功能
MOVAL,02H;80*25彩色文本模式
INT10H;BIOS10功能调用
CALLCLR;背景清屏
showINFO5;输入错误,显示提示语
showINFO6
showINFO1
showINFO2
showINFO3
showINFO4
showMUSLIST
jmpinput
RETU:
MOVAH,4CH;返回
INT21H
;*********************************************
;背景清屏
CLRPROCNEAR
MOVBH,0;第0页
MOVBL,011010B;字符属性
MOVDX,0000H;0行0列
MOVAL,'';要输出的字符
MOVCX,80*25;循环次数
MOVAH,02H;置光标位置
INT10H
MOVAH,09H;BIOS10子功能调用,输出字符
INT10H
RET
CLRENDP
;******************************************发声
GENSOUNDPROCNEAR
PUSHAX;保护寄存器
PUSHBX
PUSHCX
PUSHDX
PUSHDI
MOVAL,0B6H;写入方式控制字
OUT43H,AL;输出到控制端口
MOVDX,12H
MOVAX,348ch
DIVDI;得到发声频率
OUT42H,AL;发送低字节
MOVAL,AH
OUT42H,AL;发送高字节
INAL,61H;读取8255A的PB端口原输出值
MOVAH,AL;将原输出值保存于AH中
ORAL,3;使PB1、PB0均为1
OUT61H,AL;打开GATE2门,输出方波到扬声器
WAIT1:
MOVCX,3314;延时
callwaitf
DELAY1:
DECBX;节拍时间值减1
JNZWAIT1
MOVAL,AH;取回AH中的8255A的PB端口原输出值
OUT61H,AL;恢复8255A的PB端口
POPDI;恢复寄存器
POPDX
POPCX
POPBX
POPAX
RET
GENSOUNDENDP
;********************************************
waitfprocnear;延时子程序
pushax;保护寄存器
waitf1:
inal,61h;读取PB端口值
andal,10h;低4位清零
cmpal,ah;检查PB3是否改变
jewaitf1;等待改变
movah,al;改变,保护新端口值
loopwaitf1;继续,直到CX=0
popax;恢复寄存器
ret
waitfendp
;*********************************************
MUSICPROCNEAR;音乐子程序
PUSHDS;压入数据段
SUBAX,AX;标志位清零
PUSHAX
FREG:
MOVDI,[SI];取音符频率,送DI
CMPDI,-1;结束?
JEEND_MUS;是,退出
MOVBX,DS:
[BP];取音符持续时间
CALLGENSOUND;调用GENSOUND发声子程序
ADDSI,2;频率表指针增2
ADDBP,2;时间表指针增2
JMPFREG;继续演奏
END_MUS:
RET;返回
MUSICENDP
CODEENDS
ENDMAIN
附录2程序运行结果
程序开始运行时界面见附图1所示。
附图1开始运行界面
输入正确的字符命令后运行界面见附图2所示。
附图2正常运行界面
输入错误字符后的运行界面见附图3所示。
附图3输入错误字符界面
输入退出字符Q后运行界面见附图4所示。
然后按任意键即可退出运行界面。
附图4输入字符Q界面
附录3芯片资料
8253只有一个控制字,一个方式控制字只决定一个计数通道的工作模式。
8253的控制字格式如附表1所示,共分为4部分:
通道选择,计数器读/写方式,工作方式和计数码的选择。
附表18253控制字
D7D6D5D4D3D2D1D0
SC1
SC2
RL1
RL0
M2
M1
M0
BCD
计数器选择方式见附表2。
附表28253通道选择
SC1SC0
对应的通道
00
通道0
01
通道1
10
通道2
11
不用
计数器读/写方式选择见附表3。
附表38253读/写方式
RL1RL0
通道读写操作
00
计数器锁存
01
只读写低8位字节
10
只读写高8位字节
11
读写16位
工作方式选择见附表4。
附表48253工作方式选择
M2M1M0
工作方式选择
000
工作方式0
001
工作方式1
×10
工作方式2
×