音乐演奏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 方案设计音乐的实现主要是对乐谱中的单音符按照一定的音符频率表转化为计数器的计数频率以及喇叭发声的控制时间,通过计数产生相应的控制动作。
由此可以有两种方案比较和选择。
2.1 方案一通过编程使用软件来实现计数和喇叭发声的时间设置,控制8255A并行I/O 接口驱动喇叭发声。
CPU每执行一条指令需要耗费一定的时间,这样可以通过循环的方式设置好循环次数,实现软件计数,然后输出相应的高低电平,驱动喇叭发出对应频率和节拍的声音。
利用软件编程方式实现该功能的优点是可以减少硬件开支,便于调试和问题的查找。
缺点是CPU开支太大,利用率不高,而且时间不够精准。
2.2 方案二利用硬件实现频率计数和延时时间的控制,利用8253-5定时/计数器芯片和8255A并行I/O接口芯片。
使8253的一个通道工作在“方波发生器”模式,实端口实现发声时间的计数控制。
这样可以精现对频率的计数;利用8255A的PB3确的控制时间,减少CPU的开支。
该方案的优点是控制精度提高,同时也减少CPU的开支。
缺点是硬件开销比较多。
2.3 方案选择本文要实现的功能所需要的硬件电路并不是太复杂,一般的IBM-PC/XT/AT 机家族都带有相应的硬件电路。
在提高精度与简易程度的比较下,决定采用方案二,这样可以大大提高时间控制精度,同时减少软件程序的复杂度。
3 硬件电路IBM-PC/XT内部8253电路图如图3-1所示。
图3-1 8253电路连接图8253的通道0用于产生固定频率的始终节拍,通道1用于产生固定频率的的刷新信号,通道2用于产生频率信号,工作在方式3,计数值为6A4H=1190,方波输出频率为1.19MH Z。
此信号频率决定扬声器的音调,通道2的控制字为0B6H。
音乐产生主要用到通道2。
8253通道2的计数由8255A的PB0控制,当PB输出为高电平时,使门控GATE2为高电平。
此时,8253通道2允许计数,故通道2的输出方波受PB的控制,从而控制扬声器的音调高低。
通道2的输出能否对扬声器产生持续控制还取决于8255A的PB1。
当PB1为“0”时,OUT2不能通过“与门”;反之,则可以通过“与门”控制扬声器。
所以,扬声器发音时间的长短取决于8255A的PB1信号。
另外CPU通过读8255A的C口,得知8253通道2的状态和扬声器驱动器的状态。
4 软件设计4.1 屏幕显示设计程序运行时,屏幕显示第一界面如下:~~~~~Assembly Music Player~~~~~---------------------|PLEASE SELECT A MUSIC|---------------------A LIANGZHILAOHUB ZHENGFUQ EXIT~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~选择A、B分别演奏相应的音乐,选择Q键结束程序运行。
当输入别的按键信号时,显示出错提示信息,界面如下:ERROR! CHOOSE A B QPLEASE INPUT AGAIN!~~~~~Assembly Music Player~~~~~---------------------|PLEASE SELECT A MUSIC|---------------------A LIANGZHILAOHUB ZHENGFUQ EXIT~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~按照提示信息重新输入正确字符即可。
上述提示信息在数据段定义,类型为字节型。
首先调用BIOS中断的10H号功能设置文本模式。
程序如下:MOV AH,00H ;BIOS 10子功能MOV AL,02H ;80*25彩色文本模式INT 10H ;BIOS 10功能调用然后调用背景清屏子程序使文本屏幕清空,为输入信息作准备,清屏子程序如下:CLR PROC NEARMOV BH,0 ;第0页MOV BL,00011010B ;字符属性,蓝底绿字不闪烁MOV DX,0000H ;0行0列MOV AL,' ' ;输出的字符MOV CX,80*25 ;循环次数MOV AH,02H ;BIOS 10H子功能调用,置光标位置INT 10HMOV AH,09H ;BIOS 10H子功能调用,输出字符INT 10HRETCLR ENDP最后输出提示语字符。
输出提示语字符时,需要多次使用一段相同的输出代码,将该代码定义为宏,可以避免多次重复书写相同的代码。
不定义为子程序是为了避免多次调用使执行速度减慢。
相应宏定义语句为:SHOW MACRO bLEA DX, b ;将相应字符段的偏移地址装入DXMOV AH, 9 ;DOS 21H号中断9子功能输出多字符INT 21HENDM则相应的字符提示信息输出代码为:CALL CLRshow INFO1show INFO2show INFO3show INFO4show MUSLIST4.2 音乐发声控制一首乐曲由若干音符组成,一个音符对应一个频率。
将与一个频率对应的计数器初值写入2号计数器(端口地址为42H),扬声器就发出相应的音调,计数器初值的计算公式:计数器初值=1193182/输出频率其中,1193182Hz转换成十六进制为12348CH,因此在打开扬声器的条件下,执行下列程序段即可发出与输出频率对应的音调。
MOV AL,0B6H ;写入方式控制字OUT 43H,AL ;写入控制端口MOV DX,12HMOV AX,348CHDIV 频率值;频率转换成计数初值OUT 42H,AL ;低8位送2号计数器MOV AL,AHOUT 42H,AL ;高位送2号计数器接下来设计发声程序,发声系统受8255A芯片(端口地址为60H-63H)的两根输出线PB0和PB1的控制,PB输出的高电平使2号计数器正常工作,PB1输出高电平打开输出控制门。
发声程序代码如下:IN AL,61H ;读取8255A的PB端口原输出值MOV AH,AL ;将原输出值保存于AH中OR AL,3 ;使PB0、PB1、均为1OUT 61H,AL ;打开GATE2门,输出方波到扬声器4.3 节拍时间的实现下面控制音符的演奏时间,这是设计音乐程序的关键问题。
最直观的方法是按照谱为每一个音符规定一个演奏时间。
在遇到一首不熟悉歌曲时,初期很难确定每个音符的演唱时间,而调试程序的需大量的时间。
为每一个音符规定“单位时间”:单位时间*N=音符的延长时间其中,N为调试参数,一首歌曲只有一个调试参数。
设计程序时可以用EQU伪指令定义调试参数,初值现行估算,调试时在修改它。
节拍时间设置好以后,就可以利用延时程序,通过PB1端口控制发声的时间长短。
80x86的各种处理器采用6-66MH Z的工作频率,LOOP治理的执行时间在这些处理器上也不同。
为了建立一个与处理器无关的时间延迟,IBM采用了一个利用硬件产生时间延迟的方法,即通过监控端口61H的PB4,使PB4每15.08us触发一次,以产生一个固定不变的时间基准,在IBM-PC/XT 中的BIOS中的WAITF子程序,就是一个产生N*15.08us时间延迟的程序,调用WAITF子程序时,CX寄存器必须装入15.08us的倍数N。
本程序延时程序参考上面的原理,代码如下:waitf proc near ;延时保护程序push ax ;保护寄存器waitf1:in al,61h ;读取PB端口地址and al,10h ;低四位清零cmp al,ah ;检查是否改变je waitf1 ;等待改变mov ah,al ;改变,保护新端口值loop waitf1 ;继续,直到CX=0pop ax ;恢复寄存器retwaitf endp4.4 音乐乐谱编程组成音乐的每个音符的频率值和持续时间是音乐程序发声所需要的两个数据,根据音调与频率和时间之间的关系,把要编辑的音乐的每个音符的频率和持续时间定义成两个数据表,进而把它们写入通用发声程序。
音符频率表示见表1所示,编程产生各种音符的频率时可参照此表。
表1音符频率表(单位:赫兹)4.5 程序流程图主程序流程图如图4-1。
图4-1 主流程图MUSIC子程序流程图如图4-2。
图4-2 MUSIC子程序流程图GENSOUND子程序流程图如图4-3所示:图4-3 GENSOUND子程序流程图5 程序调试及运行结果程序编写完成后在MF2KP集成软件环境中运行,刚开始编译时,出现了很多的变量未定义的错误,经过反复检查,将拼写错误的地方一一改正,再次运行时出现了图5-1所示的错误。
图5-1 运行错误界面一开始不知道哪里出现错误,反复检查程序后仍为发现错误。
于是上网搜索“NTVDM”的意思,明白了它是一个虚拟进程运行时一个必要的程序。
猜想可能是某个参数的设置超出了该进程的参数范围。
于是重新调试程序,终于发现时调用BIOS 10H号中断0子功能中AL设置的文本模式设置错误,其中AL的值不能大于3。
修改后将AL值改为02H后,该错误得以解决。
随后发现在按照提示正确输入时,可以演奏音乐,但是当输入错误的字符时,发现屏幕并不显示错误提示语,经过多次检查和调试,发现是没有清屏程序重新设置文本显示模式,加上该段代码后程序运行正常。