音乐演奏程序设计

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

信息与电气工程学院

电子信息工程CDIO一级项目(2013/2014学年第一学期)

题目:音乐演奏程序设计

专业班级:xxxxxxxxxxxxxxxxx

学生姓名:xxxxxxx

学号:xxxxxxxxx

指导教师:xxxxxxx

设计周数:

设计成绩:

2013年12月28日

1、项目设计目的

1.1掌握接口电路的应用和设计技术。

1.2掌握汇编语言的设计思路。

1.3掌握8086的控制流程,以及8255和8253芯片的功能。

1.4用汇编程序完成键控音乐播放器,用8253定时器来产生声音。

1.5使学生能够较全面地巩固和应用课堂中所学的基本理论和程序设计方法,能够较熟练地完成汇编语言程序的设计和调试。

2、项目设计正文

2.1设计内容

要求完成一个音乐程序,即通过按下键盘上某个按键就可以按预先设定的程序播放音乐或者终止程序。比如:按大写字母“1”,唱乐曲“沂蒙山小调”;按大写字母“2”,唱乐曲“生日快乐”按大写字母“3”,唱乐曲“棉花糖”;按"4"键,退出。并且可以重复操作。

2.2总体设计思路

在IBM-PC/XT机中都带有8253-5定时/计数器,IBM-PC/AT中带有8254定时/计数器,这两种芯片功能十分类似。本文通过对8253-5定时/计数器芯片的操作实现音乐演奏。该声音接口通过汇编语言对8253-5的端口直接进行操作,可以不必要过多的使用BIOS的调用和DOS的调用。

计数器芯片有3个通道,各自具有专用功能。通道0时系统的始终节拍计时器,通道1专用于产生动态RAM的定时刷新信号,通道2用来控制计算机的扬声器的声音频率。该音乐演奏主要用到通道2的功能,使通道2工作在“方波发生器”方式,产生相应频率的音调送至喇叭驱动电路,使喇叭发出不同音调的声

音。使用8255A的PB

0控制通道2的计数,PB

1

控制通道2的输出对扬声器产生控制的时间。

人机交互包括屏幕显示提示语以及人工输入相应参数,主要应用到BIOS的10H号中断调用以及DOS 的21H号中断调用。BIOS的10H号中断调用用于显示器驱动,设置显示模式和光标位置;DOS的21H号中断调用用于单字符输入以及多字符输出显示。

音乐演奏实现的一个主要步骤是乐谱编程。通过相应的频率表将乐谱中对应的音符转化为计数器的计数初值,节奏通过延时程序转化为对喇叭发音时间的控制,从而实现音符和节拍的数字化。

2.3流程图

2.3.1主程序流程图

图2-1 主程序流程图

2.3.2 MUSIC 子程序流程图

开始

显示提示信息 接收键盘输入 是“4”?

是“1”?

是“3”?

是“2”?

退出程序

跳转到相应音乐播

放程序

调用MUSIC ,播放

音乐 显示错误提示调用

清屏程序

y

n

图2-2 MUSIC 子程序流程图

2.4通用发声程序设计原理

PC 机发声系统以8254的2号计数器为核心。系统初始化时,2号计数器I 作在“方波发生器”方式,初值为二进制数,写入顺序为先低后高,CLK2为1.193182MHz ,当计数初值为533H 时,OUT2输出的方波大约为900Hz ,经过简单的滤波之后,送至扬声器。改变1.4号计数器的计数初值就可以使扬声器发出不同频率的音响。

ROM BIOS 中有个BEEP 子程序,这能根据BL 中组出的时间计数值控制8254定时器,产生持续时间为1个或几个0.5秒,频率为896HZ 的声音,我们可以利用并修改BEEP ,使其产生任一频率的声音。为此我们需要做两点修改,首先,BEEP 程序只能产生896HZ 的声音,我们的通用发声程序应能产生任一频率的声音。其次,BEEP 产生声音的持续时间(音长)只能是0.5秒的倍数,我们希望声音的持续时间更易于调整,例如可以是10ms 的倍数。

寄存器入栈

装入音符频率值

频率值是“-1”?

调用

GENSOUND

指向下一个数据

返回主程序

主程序调用

数值应为:

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

发声程序包括3个步骤:

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

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

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

对于发音部分。PC机上的大多数输入/输出(I/O)都是由主板上的8255(或8255A)可编程序外围接口芯片(PPI)管理的。PPI包括3个8位寄存器,两个用于输入功能,一个用于输出功能。输入寄存器分配的I/O端口号为60H和62H,输出寄存器分配的I/O端口号为61H。由PPI输出寄存器中的0、1两位来选择扬声器的驱动方式。

连接到扬声器上的是定时器2,从上图可以看到,GATE2与端口61H的PB0相连,当PB0=1时,GATE2获得高电平,使定时器2可以在模式3(方波)下工作。定时器2的OUT2与端口61H的PB1通过一个与门与扬声器的驱动电路相连。当PB1=1时,允许OUT2的输出信号到达扬声器电路。因此,只有PB0和PB1同时为“1”时,才能驱动扬声器地声。通过以下指令实现:

IN AL,61H

OR AL,3

OUT 61H,AL

上面的指令用以打开扬声器,如要关闭扬声器时则为:

AND AL,0FCH

OUT 61H,AL

当从8255中采集到输入的数据时,需要确定相应的频率,所以在软件编程时要建立一个数据表:TABLE DW 493,440,392,349,329,293,261

把相应的频率送到一个寄存器上,通过公式:

计数值=533H×896÷ f=1234DCH÷ f

算出计数值,再把算得的计数值送给8253,就可产生所要频率的方波。在把计数值送8253前,必须先把8253进行初始化:

MOV AL,0B6H

OUT 43H,AL

就整个电路而言,接好电路后,通过软件编程不断地采集从8255口中输入的信号,而8个开关都接在8255的A口上,只要有开关按下,就会采集到一个数据,根据这个数据与事先编好的表对应,得到一个计数值,把这个计数值送给8253的通道2,8253的通道2工作的方式3下,这样就可以产生满足频率要求的发声方波。这个方波经驱动放大就可以使扬声器发出相应的声音。所以8255在这里完成两个任务,它不仅从A口中采集到数据,而且B口的PB1和PB0两个位要控制发声。8253的主要任务就是产生所要求发声的不同频率的方波。

2.5乐曲编辑

乐曲是按照一定的高低、长短和强弱关系组成的音调,在每一首乐曲中,每个音符的音高和音长与发声系统中的频率、节拍有关。可参考下表:

音符频率/HZ 半周期/us 音符频率/HZ 半周期/us

低1DO 262 1908 #4FA# 740 0676

#1DO# 277 1805 中5SO 784 0638

低2RE 294 1700 #5SO# 831 0602

#2RE# 311 1608 中6LA 880 0568

低3M 330 1516 #6LA# 932 0536

低4FA 349 1433 中7SI 988 0506

#4FA# 370 1350 高1DO 1046 0478

低5SO 392 1276 #DO# 1109 0451

#5SO# 415 1205 高2RE 1175 0426

低6LA 440 1136 #2RE# 1245 0402

#6LA# 466 1072 高3M 1318 0372

低7SI 494 1012 高4FA 1397 0358

中1DO 523 0956 #4FA# 1480 0338

#1DO# 554 0903 高5SO 1568 0319

中2RE 578 0842 #5S0# 1661 0292

#2RE# 622 0804 高6LA 1760 0284

中3M 659 0759 #6LA# 1865 0268

中4FA 698 0716 高7SI 1976 0253

2.6各个功能的实现

2.6.1显示功能

MOV AH,9

INT 21H

LEA DX,INFO2

INT 21H

LEA DX,MUSLIST

INT 21H

LEA DX,INFO3

INT 21H

LEA DX,INFO6

INT 21H

在此段代码中,程序显示提示作用的字符串和歌曲列表。

2.6.2音乐播放模块

MUSIC1:

LEA SI,FREG1 ;将频率表的偏移地址送入SI

LEA BP,DS:TIME1 ;将节拍时间表的偏移地址送入BP CALL MUSIC ;调用MUSIC子程序

JMP INPUT

MUSIC2:

LEA SI,FREG2

LEA BP,DS:TIME2

CALL MUSIC

JMP INPUT

MUSIC3:

LEA SI,FREG3

LEA BP,DS:TIME3

CALL MUSIC

JMP INPUT

2.6.3 MUSIC子程序

MUSIC PROC NEAR

PUSH DS

PUSH AX

FREG:

MOV DI,[SI] ;取音符频率,送DI

CMP DI,-1

JE END_MUS

MOV BX,DS:[BP] ;取音符持续时间

CALL GENSOUND ;调用GENSOUND发声子程序

ADD SI,2 ;频率表指针增2

ADD BP,2 ;时间表指针增2

JMP FREG ;继续演奏

END_MUS:

RET

MUSIC ENDP

2.6.4音乐发声控制

一首乐曲由若干音符组成,一个音符对应一个频率。将与一个频率对应的计数器初值写入2号计数器(端口地址为42H),扬声器就发出相应的音调,计数器初值的计算公式:

计数器初值=1193182/输出频率

其中,1193182Hz转换成十六进制为12348CH,因此在打开扬声器的条件下,执行下列程序段即可发出与输出频率对应的音调。

MOV AL,0B6H ;写入方式控制字

OUT 43H,AL ;写入控制端口

MOV DX,12H

MOV AX,348CH

DIV 频率值;频率转换成计数初值

OUT 42H,AL ;低8位送2号计数器

MOV AL,AH

OUT 42H,AL ;高位送2号计数器

接下来设计发声程序,发声系统受8255A芯片(端口地址为60H-63H)的两根输出线PB

0和PB

1

的控制,

PB

0输出的高电平使2号计数器正常工作,PB

1

输出高电平打开输出控制门。发声程序代码如下:IN AL,61H ;读取8255A的PB端口原输出值

OR AL,3 ;使PB

0、PB

1

、均为1

OUT 61H,AL ;打开GATE2门,输出方波到扬声器

2.6.5延时程序

利用WAITF子程序能获得任意的时间延时,而不必在考虑CPU的型号和工作频率。

具体实现如下:

waitf proc near

push ax

waitf1:

in al,61h

and al,10h

cmp al,ah

je waitf1

mov ah,al

loop waitf1

pop ax

ret

waitf endp

2.7程序执行结果

初始运行界面

正确输入时的界面

输入错误时的界面

3收获与体会

通过这次课程设计,我们对各个芯片有了进一步的了解,对各个芯片的功能有了更深刻的认识和体会,平时上课的理论知识只是停留在理论的层面,只有通过了这样的试验才能更好的体会到,做到了理论和实际的相结合,使理论知识真正运用到了实践中去。对微机原理课程的学习,使我们对汇编语言的一些指令、操作有了一定的了解,比如各个段的定义、串操作指令,还有系统中断功能的调用等等。而本次课程设计则是对所学知识的综合应用,我们会写单条语句,但把各种指令综合起来去实现特定的功能需要我们比较强的综合能力。所以这次课程设计对我们所学知识是一个加强巩固的过程。

实验过程中碰到了很多的难题和障碍,我认识到平时基础知识的重要性。只有基础知识过关,才能综合起来应用。此外,课本上学的知识是基础的,我们必须掌握的,也用到一些课本上没有的知识,需要我们自己去查资料,然后自己学习。虽然课程结束了,但是我们还是应该深入地去学习,多进行编程练习,来提高自己的熟练程度

通过本次实验,我充分认识到了,作为一个编程人员,需要十分严谨,时刻注意自己的代码,因为一

个小小的错误,比如一个标点符号的错误,都可能导致程序不能执行。还要注意自己代码的简化程度,执行效率等等,因为刚刚接触汇编语言,这方面我做得还不算好,在以后的学习过程中,应该吸取别人代码之中的优秀的地方,把它转化为自己的东西。理论与实际相结合也是非常重要的,只有理论知识是远远不够的,在实践中可能会遇到各种各样的问题,不多经历就无法感受到这一点。要在实践中提高自己的动手能力和解决问题的能力,从而学以致用。

4程序源代码

DATA SEGMENT

INFO1 DB 0DH,0AH,' WELCOME TO MY PROGRAMME!$'

INFO2 DB 0DH,0AH,' THERE ARE 3 SONGS!$'

INFO3 DB 0DH,0AH,' PLEASE SELECT WHICH ONE TO PLAY!$'

INFO4 DB 0DH,0AH,' PRESS ESC TO RETURN TO THE MAIN MENU$'

INFO5 DB 0DH,0AH,' PLEASE INPUT AGAIN!$'

INFO6 DB 0dh,0ah,' $'

INFO7 DB 0DH,0AH,' INPUT ERROR!$'

MUSLIST DB 0DH,0AH,' ==============================='

DB 0DH,0AH,' 1:YI MENG SHAN XIAO DIAO'

DB 0DH,0AH,' 2:HAPPY BIRTHDAY'

DB 0DH,0AH,' 3:MIAN HUA TANG'

DB 0DH,0AH,' 4:EXIT'

DB 0DH,0AH,' ===============================$'

;****************************************** 音乐一沂蒙山小调

FREG1 DW 294,392,330,294,330

DW 392,330,294,262,294

DW 294,392,294

DW 330,392,330,294,262,220,262

DW 262,330,294,330,196

DW 294,247,220,196,220

DW 262,294,247,220,196

DW 165,196,-1

DW 40,4 DUP(20)

DW 60,40,40

DW 40,6 DUP(20),60

DW 40,40,20,20,40

DW 20,20,20,20,60

DW 40,5 DUP(20),60

;*******************************************音乐二生日快乐FREG2 DW 196,196,220,196,262,247

DW 196,196,220,196,294,262

DW 196,196,392,330,131,247,220

DW 349,349,330,262,294,262,-1

TIME2 DW 15,15,30,30,30,60

DW 15,15,30,30,30,60

DW 15,15,4 DUP(30),60

DW 15,15,30,30,30,30,30

DW 330,349,330,294,262

DW 262,247,220,247,262,294,330,330,349,330,294,262,-1 ;***********************************************音乐三棉花糖FREG3 DW 196,262,294,330,196,262,294,330,349,392

DW 294,196,247,262,294

DW 262,165,220,247,262,294,330

DW 330,349,330,294,262,-1

TIME3 DW 10,20,20,6 DUP(10),20

DW 4 DUP(10),40

DW 6 DUP(10),20

DW 4 DUP(10),20

DW 4 DUP(10),20

DW 6 DUP(10),20,4 DUP(10),20

;*********************************************************** STACK SEGMENT

DB 200 DUP ('STACK')

STACK ENDS

CODE SEGMENT

ASSUME DS:DATA,SS:STACK,CS:CODE

START:

MOV AX,DATA

MOV DS,AX

MOV aH, 0

MOV AL,00

INT 10H

LEA DX,INFO1 ;显示字符串

MOV AH,9

INT 21H

LEA DX,INFO2

INT 21H

LEA DX,MUSLIST

INT 21H

LEA DX,INFO3

INT 21H

LEA DX,INFO6

INT 21H

INPUT:

MOV AH,01H ;从键盘接收字符

INT 21H

CMP AL,'4' ;比较字符

JE RETU ;是,返回

CMP AL,'1' ;与1比较

JE MUSIC1 ;是,播放音乐1

CMP AL,'3'

JE MUSIC3

JMP EXIT

EXIT:

call clear ;调用清屏子程序

LEA DX,INFO7 ;显示字符串

MOV AH,9

INT 21H

LEA DX,INFO5

INT 21H

LEA DX,MUSLIST

INT 21H

LEA DX,INFO3

INT 21H

LEA DX,INFO6

INT 21H

jmp input ;继续等待输入

RETU: ;返回

MOV AH,4CH

INT 21H

;***************************************************音乐播放MUSIC1:

LEA SI,FREG1 ;将频率表的偏移地址送入SI

LEA BP,DS:TIME1 ;将节拍时间表的偏移地址送入BP

CALL MUSIC ;调用音乐子程序

JMP INPUT

MUSIC2:

LEA SI,FREG2

LEA BP,DS:TIME2

MUSIC3:

LEA SI,FREG3

LEA BP,DS:TIME3

CALL MUSIC

JMP INPUT

;*****************************************************发声GENSOUND PROC NEAR

PUSH AX ;保护寄存器

PUSH BX

PUSH CX

PUSH DX

PUSH DI

MOV AL,0B6H ;写入方式控制字

OUT 43H,AL ;输出到控制端口

MOV DX,12H

MOV AX,348ch

DIV DI ;得到发声频率

OUT 42H,AL ;发送低字节

MOV AL,AH

OUT 42H,AL ;发送高字节

IN AL,61H ;读取8255A的PB端口原输出值

MOV AH,AL ;将原输出值保存于AH中

OR AL,3 ;使PB1、PB0均为1

OUT 61H,AL ;打开GATE2门,输出方波到扬声器WAIT1:

MOV CX,3314

call waitf

DEC BX ;节拍时间值减1

JNZ WAIT1

MOV AL,AH ;取回AH中的8255A的PB端口原输出值 OUT 61H,AL ;恢复8255A的PB端口

POP DI ;恢复寄存器

POP DX

POP CX

POP BX

POP AX

RET

GENSOUND ENDP

waitf proc near ;延时子程序

push ax ;保护寄存器

waitf1:

in al,61h ;读取PB端口值

and al,10h ;低4位清零

cmp al,ah

je waitf1

mov ah,al

loop waitf1

pop ax ;恢复寄存器

ret

waitf endp

;********************************************* 音乐播放

MUSIC PROC NEAR

PUSH DS

SUB AX,AX ;标志位清零

PUSH AX

FREG:

MOV DI,[SI] ;取音符频率,送DI

JE END_MUS

MOV BX,DS:[BP] ;取音符持续时间

CALL GENSOUND ;调用GENSOUND发声子程序 ADD SI,2 ;频率表指针增2

ADD BP,2 ;时间表指针增2

JMP FREG ;继续演奏

END_MUS:

RET

MUSIC ENDP

;************************************ clear!!! 清屏程序clear proc near

push ax

push bx

push cx

push dx

mov ah,6

mov al,0

mov ch,0

mov cl,0

mov dh,24

mov dl,79

mov bh,7

int 10h

pop dx

pop cx

pop bx

pop ax

ret

clear endp

CODE ENDS

5参考文献

[1]王忠明编著.微型计算机原理[M].西安电子科技大学出版社,2010年2月

[2]沈美明。IBM-PC汇编语言程序设计.北京:清华大学出版社,2001年8月

[3]孙琦,郑硕编著.汇编语言程序设计复习与考试指导(第二版)[M].北京:高等教育出版社,2006年7月

[4]李继灿.新编16/32位微型计算机原理及应用.北京:清华大学出版社,2001

[5]白中英.计算机组成原理.北京:科学出版社,2000

项目设计

评语

项目设计成绩指导教师

(签字)年月日

相关文档
最新文档