电子琴综合实验报告(汇编语言)

时间:2024.4.14

基于分频原理的多功能电子琴+节拍器

信息科学技术学院 电子学系 任伶 00548091

[摘要]

一,课题及完成情况简介:

利用TPC-H实验箱上的8253实现二级分频,同时配合以8255A,与门和DAC0832,通过扬声器放音,实现两个八度音高(包括半音)的电子琴。在软硬件相互配合下,电子琴具有弹奏和播放已存乐曲的功能,音长可控,播放速度可选,拥有美观的图形界面模拟真实琴键,且琴键随弹奏有起伏变化。利用微机内部的8253,8255A和内置扬声器,与TPC-H实验板上的8255A和LED,实现节拍器,可产生长度和速度可控的2/4拍,3/4拍及4/4拍等,LED和内置扬声器同时对节拍进行提示。

二,关键词:

8253,8255A,DAC0832,弹奏,录音,播放,用户选择

[目标要求]

一,基本功能:

1.       以微机键盘模拟真实琴键,发出标准C大调音阶和其高八度音阶,包括半音

2.       每个音可以任意长短发音,由用户的按键时间决定,模拟真实电子琴的发生效果

二,附加功能:

1. 通过编写汇编语言,实现可视化界面,便于用户操作;弹奏过程中,琴键随用户按键的按下和弹起有起落变化的效果

2. 在弹奏过程中同步录音;播放已经录制的乐曲;播放速度由用户决定,由慢速,中速和快速等选择

3. 将电子琴作为节拍器使用,输出各种节拍,有2/4拍,3/4拍及4/4拍等供用户选择,在节拍器输出的同时,有LED和微机内置扬声器作为指示;拥有LED指示是真实节拍器没有而本课题独有的功能

4. 节拍器的输出拍数有长短两种,拍速有快慢两种,均由用户选择

[设计和实施方案]

一,设计方案选择与论述

电子琴的实现方案有多种,例如基于波形叠加原理和基于分频原理等。

基于波形叠加原理,其核心在于数模转换过程,其实现的过程和需要的组件较简单;用到的芯片主要为DAC0832,数目太少,很难达到硬件使用能力的锻炼;而基于分频原理的电子琴实现能够给我更多的锻炼机会。

基于分频原理,其核心在于对分频计数的控制,多变复杂;用到的芯片包括8253,8255A,DAC0832和与门等,包括了基于波形叠加原理用到的芯片,同时我对8253和8255A的应用更熟练,便于方案可行性估计和软件调试;此方案下,TPC-H实验箱上的连线较多,更是一种对硬件处理能力的挑战。

节拍器的实现主要依靠分频和并口数据传输。

基于上述理由,我选择基于分频原理的方案来实现电子琴和节拍器的混合体。

二,所选用方案的框图

三,采用的部件(元器件),方法,算法可实现所要求的功能和指标

1.       电子琴发声部分

利用TPC-H实验箱上的8253,8255A,DAC0832和与门及相关电路连接(详见后续说明)实现电子琴弹奏和播放录音时的发声(二者算法基本一致),发生的频率和时长主要通过对用户输入(即按键)的判断,调用过程控制硬件完成。用户弹奏时,通过对按键的判断,即可知其音高,在数据列表中找到相应计数初值,赋给8253计数器0和计数器1即可。在这里要说明的是,计数器0执行的一级分频用于确定音高(不同音符的计数初值不同);计数器1执行的二级分频用于控制程序将正弦波形的离散数值写入DAC0832,从而得到模拟正弦波驱动扬声器,其计数初值不因音高变化而变化,这是因为在一个正弦周期内写入的离散数值个数是固定的,而写入频率由计数器0的输出作为GATE1控制;此为使用二级分频的缘故。按键的时长由程序计数得到,在琴键按下时,8255A的PA0口输出为零,无按键时其输出为1,因此8255A的PA0 和8253 的OUT1相与后作为8255A的PC0输入,在琴键按下时控制程序中正弦波离散数值以其频率向DAC0832 的写入,在琴键弹起时禁止此写入。对于播放录音的情况,程序从内存中读出一个音符的音高与时长,同理控制上述过程即可。

不同按键与不同音符的对应关系如下(标准C大调音阶及其高八度音阶):

通过用户选择,赋予播放速度变量不同的值,从而改变音符的时长,从而改变了乐曲的播放速度。

2.       电子琴琴键显示部分

在电子琴的图形界面设计上,采用像素点画图的方法。实现计算好电子琴静态界面各个部分的位置和大小,确定其颜色存入数据列表中,使用时调用,按照像素点的颜色和数目等信息一次画出整个键盘。

在用户弹奏时,需要显示相应琴键按下和弹起的效果。在判断音符时即确定它对应的琴键的图形中需要改动区域的像素的位置,大小和颜色,存入相应寄存器中,再调用KEYDOWN和KEYUP重新在上述区域逐点重画像素。

3.       提示信息显示部分

所有对用户的提示信息均以字符串的形式在屏幕上显示,用户的输入根据其逻辑关系驱动程序走向(详见后续说明)。

4.       节拍器工作部分

根据用户的选择,决定输出节拍的种类,长度和速度,并跳转到相应程序段,同时相应变量赋值。其中,长度即输出节拍的个数,速度决定程序延时。LED的L3~L0点亮与否由TPC-H实验箱上的8255A的PA4~PA1驱动,按一个节拍周期中强弱拍的变化依次点亮。微机内部的8253和8255A驱动内置扬声器发出不同频率的声音,按一个节拍周期中强弱拍的变化规律与LED同时对用户作出节拍提示。

四,电路原理图,软件流程图和主要软件模块说明

1.       电路原理图

2.       软件流程图

    3. 主要软件模块说明

(1)采用IBM-PC彩色图形方式,显示电子琴键盘的画面

(a)绘制出键盘的静态效果

其中,图形界面的数据缓冲区定义如下:

KEYBOARD DB 179 DUP(6); 电子琴上部的橙色背景

         ; 键盘中部

         DB 6 DUP(6),8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),6 DUP(6)

             DB 6 DUP(6),8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

             DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),6 DUP(6)

         ; 键盘下部

             DB 6 DUP(6),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

             DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

                DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

             DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),6 DUP(6)

             DB 6 DUP(6),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

             DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

             DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

             DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),6 DUP(6)

调用DRAW画出键盘的静态效果。

;-------------------DRAW----------------------

DRAW PROC NEAR

    PUSH AX

    PUSH BX

    PUSH CX

    PUSH DX

    PUSH SI

    PUSH DI

   

    MOV AX,DATA; 段寄存器初始化

    MOV DS,AX

   

    MOV AH,0; 设置屏幕显示为320X200

    MOV AL,0DH; 彩色图形(EGA)

    INT 10H

    MOV SI,0; 从第一个像素开始

    MOV CX,66; 列

    MOV DX,62; 行

    LEA BX,KEYBOARD

    ; 绘制电子琴上部的橙色背景

    PART1:

        MOV DI,[BX+SI]; 取像素值

        MOV AX,DI

       

        MOV AH,0CH

        INT 10H

        INC DX

   

        CMP DX,82; 一行画完了吗?

        JNE PART1; 若没有则继续

   

        MOV DX,62; 画下一行

        INC SI

        INC CX

        CMP CX,245; 所有的行都画完了吗?

        JNZ PART1; 若没有则继续

    ; 绘制电子琴中部黑白键交替的情景

    MOV CX,66

    MOV DX,82

    LEA BX,KEYBOARD; 现在SI=167

    PART2:

        MOV DI,[BX+SI]

        MOV AX,DI

       

        MOV AH,0CH

        INT 10H

        INC DX

        CMP DX,101

        JNE PART2

       

        MOV DX, 82

        INC SI

        INC CX

        CMP CX, 245

        JNZ PART2

;绘制电子琴中部灰白交替的情况(此处的灰色部分对应于上处的黑色部分,表示黑键

;的立体感)

    MOV CX, 66

   MOV DX, 101

   LEA BX, KEYBOARD

    PART3:

        MOV DI,[BX+SI]

        MOV AX, DI

        MOV AH, 0CH

        INT 10H

        INC DX

        CMP DX, 103

        JNE PART3

        MOV DX, 101

        INC SI

        INC CX

        CMP CX, 245

        JNZ PART3

;绘制键盘的下部分,白色、中间夹着黑色线条表示不同的白键

    MOV CX, 66

   MOV DX, 103

   LEA BX, KEYBOARD

    PART4:

        MOV DI, [BX+SI]

        MOV AX, DI

        MOV AH, 0CH

        INT 10H

        INC DX

        CMP DX, 116

        JNE PART4

        MOV DX, 103

        INC SI

        INC CX

        CMP CX, 245

        JNZ PART4

;绘制键盘的下部分,将横坐标方向上对应于上行白色的部分对应成灰色,显示立体感

    MOV CX, 66

   MOV DX, 116

   LEA BX, KEYBOARD

    PART5:

        MOV DI, [BX+SI]

        MOV AX, DI

        MOV AH, 0CH

        INT 10H

        INC DX

        CMP DX, 119

        JNE PART5

        MOV DX, 116

        INC SI

        INC CX

        CMP CX, 245

        JNZ PART5

    POP DI

    POP SI

    POP DX

    POP CX

    POP BX

    POP AX

    RET

DRAW ENDP

(b)调用KEYDOWN和KEYUP画出琴键按下和弹起的动态效果

当白键按下时,对应白色键下面的灰色部分将被涂成白色,等按键弹起时恢复灰色。当黑键按下时,对应黑色键下面的灰色部分将被涂成黑色,等按键弹起时恢复灰色。

由于白键和黑键的宽度不一样,在下面相应位置将灰色覆盖的颜色也分别是白色和黑色,并且开始绘制的横纵坐标不一样,因此程序中用CX记录该开始涂的点的横坐标,DX记录纵坐标,COLOR1表示KEYUP中应涂上的颜色,LEN表示涂的纵向长度,WID表示涂的横向宽度。COLOR2表示KEYDOWN中应涂上的颜色。

;--------------KEYDOWN-------------------

KEYDOWN PROC NEAR

    PUSH AX

    PUSH BX

    PUSH CX

    PUSH DX

    PUSH SI

    PUSH DI

   

    MOV SI,0

    MOV DI,0

    MOV AH,0CH

    MOV AL,COLOR1; 确定图样颜色

    DOWN:

        INT 10H

        INC DX

        INC DI

        CMP DI,LEN; 长度方向画完了吗?

        JNE DOWN; 没画完则继续

        SUB DX,LEN

        MOV DI,0

        INC CX

        INC SI

        CMP SI,WID; 宽度方向画完了吗?

        JNE DOWN; 没画完则继续

    POP DI

    POP SI

    POP DX

    POP CX

    POP BX

    POP AX

    RET

KEYDOWN ENDP

;---------------KEYUP---------------------------

KEYUP PROC NEAR

    PUSH AX

    PUSH BX

    PUSH CX

    PUSH DX

    PUSH SI

    PUSH DI

   

    MOV SI,0

    MOV DI,0

    MOV AH,0CH

    MOV AL,COLOR2; 确定图样颜色

    UP:

        INT 10H

        INC DX

        INC DI

        CMP DI,LEN; 长度方向画完了吗?

        JNE UP; 没画完则继续

        SUB DX,LEN

        MOV DI,0

        INC CX

        INC SI

        CMP SI,WID; 宽度方向画完了吗?

        JNE UP; 没画完则继续

    POP DI

    POP SI

    POP DX

    POP CX

    POP BX

    POP AX

    RET

KEYUP ENDP

(2)用户弹奏,实现不同音高输出和时长控制

不同音高对应的初级分频计数初值记录在SCALE中:

    SCALE DW 476,450,424,402,378,356,336,316,300,282,268,252

          DW 238,224,210,200,188,182,170,158,150,140,132,124

DAC0832将正弦波的离散数值进行数模转换变为模拟量输出时使用的正弦波离散数值存储于SIN中(这是一个周期中对模拟正弦波进行32次等间隔抽样量化得到的结果):

    SIN DB 127,139,152,164,176,187,198,208

        DB 217,225,233,239,244,249,252,253

        DB 254,253,252,249,244,239,233,225

        DB 217,208,198,187,176,164,152,139

        DB 127,115,102,90,78,67,56,46

        DB 37,29,21,15,10,5,2,1

        DB 0,1,2,5,10,15,21,29

            DB 37,46,56,67,78,90,102,115

以下程序段在按键已经完成音符判断的基础上实现声音的输出,音高和时长的记录存储(其中,BX存放频率数组指针偏移量):

    PLAY:

        CALL KEYDOWN; 画出键按下的图样

        PUSH BX

        PUSH CX

        PUSH DX

        MOV DX,288H; 发声

        MOV AL,1

        OUT DX,AL

        MOV [DI],BX; 存储频率(数组偏移量)

        INC DI

        INC DI

       

        MOV AL,00110110B; 8253初始化,计数器0,读写16位

        MOV DX,283H    ; 工作方式3,二进制计数

        OUT DX,AL

        MOV AX,[BX+SI]; 赋初值,即设定频率

        MOV DX,280H

        OUT DX,AL

        MOV AL,AH

        OUT DX,AL

        MOV DX,283H

        MOV AL,01010110B;8253初始化,计数器1,低8位读写

        OUT DX,AL;工作与方式3,二进制计数

       

        MOV DX,281H;输出计数器初值,控制向DAC0832写入的频率

        MOV AL,32

        OUT DX,AL

        MOV BX,00H; 开始记录按键时长

    PBEG:

        PUSH SI

        LEA SI,SIN; 输出一个周期的正弦波形

        MOV CX,32

    L0:    

        WAIT1:

            MOV DX,2B0H

            MOV AL,[SI]

            OUT DX,AL; 取得正弦量化数值,送入DAC

            MOV DX,28AH

            IN AL,DX

            CMP AL,01H; 分频控制信号的正半周期

            JZ WAIT1

        INC SI

        WAIT2:

            MOV DX,2B0H

            MOV AL,[SI]

            OUT DX,AL; 取得正弦量化数值,送入DAC

            MOV DX,28AH

            IN AL,DX

            CMP AL,00H; 分频控制信号的负半周期

            JZ WAIT2

        INC SI

        LOOP L0

        POP SI

        INC BX; 即输出一个周期的正弦波形,记录时长有一个增量

    HOLD:

        IN AL,60H

        TEST AL,80H

        JZ PBEG; 如果按键未放开,继续记录

       

        MOV DS:[DI],BX; 存储按键时长

        INC DI

        INC DI

        MOV AX,BUFFER; 缓冲区指针后移

        INC AX

        INC AX

        INC AX

        INC AX

        MOV BUFFER,AX

        MOV DX,288H; 停止发声

        MOV AL,0

        OUT DX,AL

        MOV DX,2B0H; DAC输入为零,不发声

        MOV AL,0

        OUT DX,AL

    POP DX

    POP CX

    POP BX

    CALL KEYUP; 画出键恢复的图样

(3)调用LIST进行已存乐曲的播放

MODE存放用户选择的播放速度模式(慢速,中速或快速),其值控制每个音的时长,从而达到控制乐曲速度的效果。

;----------------------LIST----------------------------

LIST PROC NEAR

    LISTMENU:

        LEA DX,LMENU; 显示放录音时的菜单

        MOV AH,09H

        INT 21H

    LIN:

        MOV AH,07H; 读入播放速度或返回主菜单的要求

        INT 21H

        CMP AL,'M'

        JNZ FFF

        JMP MAINMENU; 返回主菜单

        FFF:

            CMP AL,'1'

            JNZ MMM

            MOV MODE,1; 快速播放

            JMP NEXT

        MMM:

            CMP AL,'2'

            JNZ LLL

            MOV MODE,4; 中速播放

            JMP NEXT

        LLL:

            CMP AL,'3'

            JNZ LIN; 按错键了则重新读入

            MOV MODE,8; 慢速播放

    NEXT:

        LEA DX,LBEG; 显示播放录音时的提示语

        MOV AH,09H

        INT 21H

    LI:

        LEA DI,BUFFER

        INC DI

        INC DI

    LIO:

        MOV BX,[DI]

        INC DI

        INC DI

        CMP BX,0FFFFH

        JZ LI_END; 如果是录音的结尾则结束播放,否则继续

        MOV DX,288H; 使能喇叭,开始播放

        MOV AL,1

        OUT DX,AL

        MOV DX,283H

        MOV AL,00110110B; 8253初始化,计数器0,16位读写

        OUT DX,AL; 工作于方式3,二进制计数

        MOV DX,280H; 输出计数初值,即控制声音的频率

        MOV AX,[BX+SI]

        OUT DX,AL

        MOV AL,AH

        OUT DX,AL

       

        MOV DX,283H

        MOV AL,01010110B;8253初始化,计数器1,低8位读写

        OUT DX,AL;工作与方式3,二进制计数

       

        MOV DX,281H;输出计数器初值,控制向DAC0832写入的频率

        MOV AL,32

        OUT DX,AL

        MOV BX,[DI]; 取得声音时长

        MOV AX,BX; 加以播放速度的控制

        MUL MODE

        MOV BX,AX

        INC DI

        INC DI

        DELAY:     ; 延时输出声音

            PUSH SI

            LEA SI,SIN; 输出一个周期的正弦波

            MOV CX,32; 频率由计数器0和1的分频结果控制

            L1:

            WAIT3:

                MOV DX,2B0H; 在分频输出方波为1时输出正弦波的第2n个值

                MOV AL,[SI]; 其中n=0,1,2,...,31

                OUT DX,AL; 将正弦波的数值写入DAC,由其转化为模拟量输出

                MOV DX,28AH

                IN AL,DX

                CMP AL,01H

                JZ WAIT3

            INC SI

            WAIT4:

                MOV DX,2B0H; 在分频输出方波为0时输出正弦波的第2n+1个值

                MOV AL,[SI]

                OUT DX,AL

                MOV DX,28AH

                IN AL,DX

                CMP AL,00H

                JZ WAIT4

            INC SI

            LOOP L1

            POP SI

            DEC BX

            JNZ DELAY

        MOV DX,288H; 停止喇叭输出

        MOV AL,0

        OUT DX,AL

        MOV DX,2B0H; DAC输入为零,不发声

        MOV AL,0

        OUT DX,AL

        JMP LIO; 播放下一个音符

    LI_END:          ; 显示播放结束提示语

        LEA DX,LEND

        MOV AH,09H

        INT 21H

    JMP LISTMENU; 回到播放主菜单

    RET

LIST ENDP

(4)调用RETHYM进行节拍种类和长度的选择

;--------------RYTHEM--------------------

RYTHEM PROC NEAR

    RYTHMENU:

        LEA DX,RMENU; 输出节拍器菜单

        MOV AH,09H

        INT 21H

    RIN:

        MOV AH,07H

        INT 21H

        CMP AL,'M'

        JNZ TEST_BIN

        JMP MAINMENU; 返回主菜单

        TEST_BIN:

            CMP AL,'2'

            JNZ TEST_TRI

            JMP BIN; 2/4拍

        TEST_TRI:

            CMP AL,'3'

            JNZ TEST_QUA

            JMP TRI; 3/4拍

        TEST_QUA:

            CMP AL,'4'

            JNZ RIN; 按错键了则重新读入

            JMP QUA; 4/4拍

    BIN:

        LEA DX,R4LEN; 请用户输入节拍的持续长度

        MOV AH,09H

        INT 21H

        MOV AH,07H

        INT 21H

        CMP AL,'S'

        JZ BIN_S; 想要较短的

        CMP AL,'L'

        JZ BIN_L; 想要较长的

        JMP BIN

    BIN_S:

        MOV RLEN,10; 节拍次数赋值

        CALL R_BINARY; 开始产生节拍

        JMP RYTH_END

    BIN_L:

        MOV RLEN,20

        CALL R_BINARY

        JMP RYTH_END

    TRI:

        LEA DX,R4LEN

        MOV AH,09H

        INT 21H

        MOV AH,07H

        INT 21H

        CMP AL,'S'

        JZ TRI_S

        CMP AL,'L'

        JZ TRI_L

        JMP TRI

    TRI_S:

        MOV RLEN,10

        CALL R_TRIPLEX

        JMP RYTH_END

    TRI_L:

        MOV RLEN,20

        CALL R_TRIPLEX

        JMP RYTH_END

    QUA:

        LEA DX,R4LEN

        MOV AH,09H

        INT 21H

        MOV AH,07H

        INT 21H

        CMP AL,'S'

        JZ QUA_S

        CMP AL,'L'

        JZ QUA_L

        JMP QUA

    QUA_S:

        MOV RLEN,10

        CALL R_QUADRUPLE

        JMP RYTH_END

    QUA_L:

        MOV RLEN,20

        CALL R_QUADRUPLE

        JMP RYTH_END

    RYTH_END:          ; 显示结束提示语

        LEA DX,REND

        MOV AH,09H

        INT 21H

    JMP RYTHMENU; 回到节拍器菜单

    RET

RYTHEM ENDP

(5)调用R_BINARY产生2/4拍

;-------------RYTHEM OF BINARY---------------

R_BINARY PROC NEAR

    LEA DX,R4SPEED; 请用户输入想要的速度

    MOV AH,09H

    INT 21H

BIN_SPEED:

    MOV AH,07H

    INT 21H

    CMP AL,'S'

    JZ BIN_SL; 慢速

    CMP AL,'F'

    JZ BIN_F; 快速

    JMP BIN_SPEED

BIN_SL: MOV RSPEED,10; 速度赋值

    JMP BIN_START

BIN_F:  JNZ BIN_SPEED

    MOV RSPEED,5

BIN_START:

    LEA DX,RBEG; 显示开始产生节拍的提示语

    MOV AH,09H

    INT 21H

        MOV CX,RLEN; 产生节拍次数

    LBIN:

        PUSH CX

        MOV DX,288H; 控制LED指示灯

        MOV AL,0; 先清零

        OUT DX,AL

        MOV AL,00000100B; 强拍,L1亮

        OUT DX,AL

        CALL BEEP1; 输出强拍提示音

        MOV AH,86H; 延时

        MOV CX,RSPEED

        MOV DX,0

        INT 15H

        MOV DX,288H

        MOV AL,00000010B; 弱拍,L0亮

        OUT DX,AL

        CALL BEEP3; 输出弱拍提示音

        MOV AH,86H; 延时

        MOV CX,RSPEED

        MOV DX,0

        INT 15H

        POP CX

        LOOP LBIN

            MOV DX,288H; 全部节拍完成后,LED清零

            MOV AL,00000000B

            OUT DX,AL

    RET

R_BINARY ENDP

R_TRIPLEX和R_QUADRUPLE分别用于产生3/4拍和4/4拍,程序结构与R_BINARY同理,此处不再赘述,具体代码见于完整程序代码。

(5)调用BEEP1产生重拍提示音

;------------------BEEP1----------------

BEEP1 PROC NEAR;强拍提示音,高频  

    PUSH CX

    PUSH BX

   

    MOV AL,10110110B; 微机8253计数器2方式3,16位二进制计数

    OUT 43H,AL; 微机8253端口地址为40H~43H

        MOV AX,298; 计数初值1.19MHz/4KHz=298

    OUT 42H,AL

    MOV AL,AH

    OUT 42H,AL

    IN AL,61H; 读微机8255A PB口

    MOV AH,AL; 将微机8255APB口数据暂存

    OR AL,03H; 使微机8255PB口PB1(相与OUT2),PB0(GATE2)均为1

    OUT 61H,AL; 打开GATE2,使OUT2输出至扬声器

    MOV CX,0

    MOV BL,40

BEEP_DELAY1:            ; 延时出声

    LOOP BEEP_DELAY1

    DEC BL

    JNZ BEEP_DELAY1

    MOV AL,AH; 恢复微机8255A的PB口原值,停止发声

    OUT 61H,AL

    POP BX

    POP CX

    RET

BEEP1 ENDP

BEEP2和BEEP3分别用于产生次强拍和弱拍的提示音,程序结构与BBEP1同理,此处不再赘述,具体代码见于完整程序代码。

[实施条件]

一,硬件设备及连线方法:

微机一台,TPC-H通用微机接口实验箱一个,扬声器一个。

8253连线:CS---280H, CLK0---1MHz, GATE0---+5V, OUT0---CLK1, GATE1---+5V, OUT1---与门输入。

8255连线:CS---288H, PA0---与门输入, PC0---与门输出, PA1~PA4---LED L3~LO。

扬声器连接TPC-H实验箱上的扬声器接口即可。

二,软件设备:

汇编语言编程系列工具:MASM, LINK, EDIT等,MS-DOS, Windows 98操作系统等。

[功能测试及结果分析]

一,测量方法和所用仪器:

电子琴和节拍器均在用户界面下完成操作,因此测试方法为直接按程序提示进行操作,所需仪器同上所述。

二,测试数据及结果分析:

测试结果为所属功能均可正常实现,程序运行正常。

在此对正弦波的抽样量化点数的选择进行分析说明。

最初我没有使用DAC0832进行数模转换,而是直接将扬声器连接到与门输出。电子琴在这种情况下可以正常发声,但鉴于接口处电流电压等参数匹配的考虑,使用DAC0832更科学,连接方法更简单。

首先使用DAC0832时,正弦波的抽样量化点数取为32,电子琴的每一个音符均可正常发生,但仔细听就会发现,在持续时间较长的发声中有“嘟嘟嘟”这样不连续的声音存在,这种现象在慢速播放已录乐曲时尤为明显;这主要是正弦波在进行DAC时抽样量化点数太少造成的。因此考虑将上述点数取为256,这样能很好地解决声音不连续的问题,但数模转换用时过长,导致程序不能及时相应琴键短促的按下和弹起。经过尝试,将点数定为64,这样既能保证声音的连续输出,又不会在数模转换上延时过多,使程序最优化。

三,功能及使用方法说明:

功能在之前已有相熟,此处着重说明使用方法。

用户运行程序后,出现主菜单,按P键自行弹奏,按L键播放已经录制的乐曲,按R键进入节拍器,按<Esc>键结束程序,返回DOS。

进入自行弹奏后,出现电子琴键盘,不同按键与不同音符的对应关系如下(标准C大调音阶及其高八度音阶):

音长即为按键时间。随着键盘的按下与弹起,屏幕上的相应琴键也有起伏变化,如有非上表中的键按下,则忽略之。按<Esc>键返回主菜单。

进入播放功能后,出现播放菜单,用户可根据菜单提示自行选择播放速度,按1键为快速,按2键为中速,按3键为慢速,按M键返回主菜单。选择播放速度后,即出现开始播放的提示语,同时开始播放乐曲,播放结束后亦出现提示语,并呈现播放菜单供用户继续选择。

进入节拍器后,出现节拍器菜单,用户可根据菜单提示自行选择节拍种类按2键为2/4拍,按3键为3/4拍,按4键为4/4拍,按M键返回主菜单。选择完种类后,用户被要求继续选择节拍长度,按S键选择短(即产生10个周期的节拍),按L键选择长(即产生20个周期的节拍)。之后用户被要求选择节拍速度,按S键为慢速,按F键为快速。在上述选择过程中,按错的键被忽略,用户继续输入正确的按键即可。选择结束后,出现开始产生节拍的提示语,同时开始产生节拍,伴有随拍子强弱变化的提示音和LED闪亮。结束后亦出现提示语,并呈现节拍器菜单供用户继续选择。

[讨论]

一,存在的问题:

我认为,实验中的不足之处在于与真实电子琴和节拍器的差距。

1. 真实电子琴的音量可调,同时具有减弱效果;这主要是由于没有使用基于波形叠加原理的方案,从而无法灵活控制正弦波的振幅。再者,未能实现和弦;和弦涉及复杂的数学计算,难以掌握。同时,未能有效的对各种乐器的音色进行模仿,这需要输出功放有良好的音效,且需要对各种乐器乐音的波形特征有充分的了解。

2. 真实的节拍器有种类更多的节拍可供选择,包括3/8拍等,同时拍速灵活可调。这需要增加程序容量,设立专门变量控制拍速,即控制延时。

二,改进的措施:

1. 改变声音的幅度必须采用波形叠加的输出形式,可考虑事先将减弱的波形存储在内存里,使用时调用即可;可以参照对播放速度的控制,设立专门变量控制振幅,即在基本振幅上乘以此系数。对于和弦的控制,也需要以波形叠加为基础,通过波形中不同的频率成分体现和弦效果,为保证输出相应速度,可以事先将各种和弦计算并存储,通过按键识别调用相应数据输出。对于各种乐器音色的模仿,亦可将其特定波形存储后调用输出;同时这也需要高保真功放,否则仅仅用实验中的喇叭是很难分辨出这些音色的区别。

2. 对于真是节拍器的模仿,可以增加程序的选择分支,同时设立专门变量取得用户想要的拍速。

三,展望:

为了更好的实现人机交互,可以考虑使用汇编语言和高级语言的混合编程,从而有效读入用户对音量,拍速等的精细要求。

同时,鉴于电子琴使用的芯片和扬声器在TPC-H实验箱上,而节拍器的分频芯片和扬声器在微机内部,两者没有相互冲突的部分,可以考虑将电子琴和节拍器结合起来,即在弹奏或是播放录音的同时有节拍器输出节拍供用户掌握节奏,这样实用效果更强大。

[结束语]

      十多年练习小提琴的经历让我对乐器和节拍有独特的感情,所以毫不犹豫地选择了这个课题作为微机综合实验。一路走来,学到的东西很多很多。一方面,增强了我对8253,8255A和DAC0832等芯片的理解与运用能力,也很好的锻炼了软硬件相结合的处理能力;另一方面,又更深刻的感受到了汇编语言的强大功能和独到魅力。相信这些收获的知识和方法不论对以后的学习还是对将来的科研都将有极大的帮助。

在这里,要特别感谢在实验过程中给与我帮助的老师和同学。赵思同学帮助我更好的理解了图形界面的用法,杨老师耐心认真地解答我遇到的各种问题。十分感谢老师和同学们热情启发和无尽支持,这些我都会受益终身,谢谢你们。

[附录]

完整程序代码如下:

;------------------------DATA-------------------------

DATA SEGMENT

       KEYBOARD DB 179 DUP(6)

               DB 6 DUP(6),8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

               DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

               DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),1 DUP(0)

               DB 8 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),5 DUP(7),7 DUP(0),8 DUP(7),6 DUP(6)

               DB 6 DUP(6),8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

                DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

                DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),1 DUP(0)

                DB 8 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),5 DUP(7),7 DUP(8),8 DUP(7),6 DUP(6)

                DB 6 DUP(6),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

                DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

                  DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0)

                DB 11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),1 DUP(0),11 DUP(7),6 DUP(6)

                DB 6 DUP(6),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

                DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

                DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0)

                DB 11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),1 DUP(0),11 DUP(8),6 DUP(6)

       BUFFER DW 1024 DUP(?)

       SCALE DW 476,450,424,402,378,356,336,316,300,282,268,252

             DW 238,224,210,200,188,182,170,158,150,140,132,124

       SIN DB 127,139,152,164,176,187,198,208

           DB 217,225,233,239,244,249,252,253

           DB 254,253,252,249,244,239,233,225

           DB 217,208,198,187,176,164,152,139

           DB 127,115,102,90,78,67,56,46

           DB 37,29,21,15,10,5,2,1

           DB 0,1,2,5,10,15,21,29

           DB 37,46,56,67,78,90,102,115

       MMENU DB 'PIANO',0DH,0AH

             DB 'Main Menu:',0DH,0AH

             DB 'P for playing',0DH,0AH

             DB 'L for listening to recorded music',0DH,0AH

             DB 'R for the rythem generator',0DH,0AH

             DB '<Esc> for exit',0DH,0AH,'$'

       LMENU DB '1 for fast',0DH,0AH

             DB '2 for middle',0DH,0AH

             DB '3 for slow',0DH,0AH

             DB 'M for returning to the main menu',0DH,0AH,'$'

       LBEG DB 'Recorded music now',0DH,0AH,0DH,0AH,'$'

       LEND DB 'End of the record',0DH,0AH,0DH,0AH,'$'

       RMENU DB 'Input the kind of rythem you want',0DH,0AH

             DB '2, 3 or 4',0DH,0AH

             DB 'M for returning to the main menu',0DH,0AH,'$'

       R4LEN DB 'Input the length of the rythem',0DH,0AH

             DB 'S for short, L for long',0DH,0AH,'$'

       RLEN DW ?

       R4SPEED DB 'What speed do you like?',0DH,0AH

              DB 'S for slow',0DH,0AH

              DB 'F for fast',0DH,0AH

       RSPEED DW ?

       RBEG DB 'Rythem generation now',0DH,0AH,0DH,0AH,'$'

       REND DB 'End of the rythem generation',0DH,0AH,0DH,0AH,'$'

       COLOR1 DB ?; 用于画出键盘按下的情况

       COLOR2 DB ?; 用于画出键盘恢复的情况

       WID DW ?; 用于画出键盘按下和恢复的情况

       LEN DW ?; 用于画出键盘按下和恢复的情况

       MODE DB ?; 用于判别播放录音的快慢: fast, middle or slow

DATA ENDS

;-------------------------STACK----------------------------------

STACK SEGMENT STACK

       STCK DW 1024 DUP(?)

STACK ENDS

;-------------------------CODE-----------------------------------

CODE SEGMENT

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

START:

       MOV AX,DATA; 段寄存器初始化

       MOV DS,AX

       MOV AX,STACK

       MOV SS,AX

       LEA SI,SCALE

       LEA DI,BUFFER

       INC DI

       INC DI

       MOV DX,28BH; 8255初始化

       MOV AL,10000001B; 写方式控制字,端口A工作于方式0,输出

       OUT DX,AL       ;端口C下半部工作与方式0,输入 

       MOV DX,288H

       MOV AL,0; 端口A输出低电平,不发声

       OUT DX,AL

       MOV DX,2B0H; DAC输入为零,不发声

       MOV AL,0

       OUT DX,AL

      

       MOV AX,00H; 寄存器清零

       MOV BX,00H

       MOV CX,00H

       MOV DX,00H

      

       MAINMENU:

              LEA DX,MMENU; 输出主菜单

              MOV AH,09H

              INT 21H

              MOV AH,08H; 读键盘输入

              INT 21H

              CMP AL,1BH

              JNZ PP

              MOV AH,00H; 如果是<Esc>,则恢复正常显示并退出

              MOV AL,03H

              INT 10H

              JMP OVER

              PP:       ; 如果不是<Esc>,则开始工作

                     CMP AL,'P'

                     JNE RR

                     CALL DRAW; 画出电子琴键盘界面

                     CALL PIANO; 开始弹琴

                     JMP MAINMENU; 重新回到主菜单

              RR:

                     CMP AL,'R'

                     JNE LL

                     CALL RYTHEM; 节拍器开始工作

                     JMP MAINMENU

              LL:

                     CMP AL,'L'

                     JNE MAINMENU; 按错键了,返回主菜单

                     CALL LIST; 开始放录音

                     JMP MAINMENU; 重新回到主菜单

       OVER:

              MOV AH,4CH; 返回DOS

              INT 21H

;----------------------LIST----------------------------

LIST PROC NEAR

       LISTMENU:

              LEA DX,LMENU; 显示放录音时的菜单

              MOV AH,09H

              INT 21H

       LIN:

              MOV AH,07H; 读入播放速度或返回主菜单的要求

              INT 21H

              CMP AL,'M'

              JNZ FFF

              JMP MAINMENU; 返回主菜单

              FFF:

                     CMP AL,'1'

                     JNZ MMM

                     MOV MODE,1; 快速播放

                     JMP NEXT

              MMM:

                     CMP AL,'2'

                     JNZ LLL

                     MOV MODE,4; 中速播放

                     JMP NEXT

              LLL:

                     CMP AL,'3'

                     JNZ LIN; 按错键了则重新读入

                     MOV MODE,8; 慢速播放

       NEXT:

              LEA DX,LBEG; 显示播放录音时的提示语

              MOV AH,09H

              INT 21H

       LI:

              LEA DI,BUFFER

              INC DI

              INC DI

       LIO:

              MOV BX,[DI]

              INC DI

              INC DI

              CMP BX,0FFFFH

              JZ LI_END; 如果是录音的结尾则结束播放,否则继续

              MOV DX,288H; 使能喇叭,开始播放

              MOV AL,1

              OUT DX,AL

              MOV DX,283H

              MOV AL,00110110B; 8253初始化,计数器0,16位读写

              OUT DX,AL; 工作于方式3,二进制计数

              MOV DX,280H; 输出计数初值,即控制声音的频率

              MOV AX,[BX+SI]

              OUT DX,AL

              MOV AL,AH

              OUT DX,AL

             

              MOV DX,283H

              MOV AL,01010110B;8253初始化,计数器1,低8位读写

              OUT DX,AL;工作与方式3,二进制计数

             

              MOV DX,281H;输出计数器初值,控制向DAC0832写入的频率

              MOV AL,32

              OUT DX,AL

              MOV BX,[DI]; 取得声音时长

              MOV AX,BX; 加以播放速度的控制

              MUL MODE

              MOV BX,AX

              INC DI

              INC DI

              DELAY:     ; 延时输出声音

                     PUSH SI

                     LEA SI,SIN; 输出一个周期的正弦波

                     MOV CX,32; 频率由计数器0和1的分频结果控制

                     L1:

                     WAIT3:

                            MOV DX,2B0H; 在分频输出方波为1时输出正弦波的第2n个值

                            MOV AL,[SI]; 其中n=0,1,2,...,31

                            OUT DX,AL; 将正弦波的数值写入DAC,由其转化为模拟量输出

                            MOV DX,28AH

                            IN AL,DX

                            CMP AL,01H

                            JZ WAIT3

                     INC SI

                     WAIT4:

                            MOV DX,2B0H; 在分频输出方波为0时输出正弦波的第2n+1个值

                            MOV AL,[SI]

                            OUT DX,AL

                            MOV DX,28AH

                            IN AL,DX

                            CMP AL,00H

                            JZ WAIT4

                     INC SI

                     LOOP L1

                     POP SI

                     DEC BX

                     JNZ DELAY

              MOV DX,288H; 停止喇叭输出

              MOV AL,0

              OUT DX,AL

              MOV DX,2B0H; DAC输入为零,不发声

              MOV AL,0

              OUT DX,AL

              JMP LIO; 播放下一个音符

       LI_END:          ; 显示播放结束提示语

              LEA DX,LEND

              MOV AH,09H

              INT 21H

       JMP LISTMENU; 回到播放主菜单

       RET

LIST ENDP

;--------------RYTHEM--------------------

RYTHEM PROC NEAR

       RYTHMENU:

              LEA DX,RMENU; 输出节拍器菜单

              MOV AH,09H

              INT 21H

       RIN:

              MOV AH,07H

              INT 21H

              CMP AL,'M'

              JNZ TEST_BIN

              JMP MAINMENU; 返回主菜单

              TEST_BIN:

                     CMP AL,'2'

                     JNZ TEST_TRI

                     JMP BIN; 2/4拍

              TEST_TRI:

                     CMP AL,'3'

                     JNZ TEST_QUA

                     JMP TRI; 3/4拍

              TEST_QUA:

                     CMP AL,'4'

                     JNZ RIN; 按错键了则重新读入

                     JMP QUA; 4/4拍

       BIN:

              LEA DX,R4LEN; 请用户输入节拍的持续长度

              MOV AH,09H

              INT 21H

              MOV AH,07H

              INT 21H

              CMP AL,'S'

              JZ BIN_S; 想要较短的

              CMP AL,'L'

              JZ BIN_L; 想要较长的

              JMP BIN

       BIN_S:

              MOV RLEN,10; 节拍次数赋值

              CALL R_BINARY; 开始产生节拍

              JMP RYTH_END

       BIN_L:

              MOV RLEN,20

              CALL R_BINARY

              JMP RYTH_END

       TRI:

              LEA DX,R4LEN

              MOV AH,09H

              INT 21H

              MOV AH,07H

              INT 21H

              CMP AL,'S'

              JZ TRI_S

              CMP AL,'L'

              JZ TRI_L

              JMP TRI

       TRI_S:

              MOV RLEN,10

              CALL R_TRIPLEX

              JMP RYTH_END

       TRI_L:

              MOV RLEN,20

              CALL R_TRIPLEX

              JMP RYTH_END

       QUA:

              LEA DX,R4LEN

              MOV AH,09H

              INT 21H

              MOV AH,07H

              INT 21H

              CMP AL,'S'

              JZ QUA_S

              CMP AL,'L'

              JZ QUA_L

              JMP QUA

       QUA_S:

              MOV RLEN,10

              CALL R_QUADRUPLE

              JMP RYTH_END

       QUA_L:

              MOV RLEN,20

              CALL R_QUADRUPLE

              JMP RYTH_END

       RYTH_END:          ; 显示结束提示语

              LEA DX,REND

              MOV AH,09H

              INT 21H

       JMP RYTHMENU; 回到节拍器菜单

       RET

RYTHEM ENDP

;--------------------------------------------

;-------------RYTHEM OF BINARY---------------

R_BINARY PROC NEAR

       LEA DX,R4SPEED; 请用户输入想要的速度

       MOV AH,09H

       INT 21H

BIN_SPEED:

       MOV AH,07H

       INT 21H

       CMP AL,'S'

       JZ BIN_SL; 慢速

       CMP AL,'F'

       JZ BIN_F; 快速

       JMP BIN_SPEED

BIN_SL: MOV RSPEED,10; 速度赋值

       JMP BIN_START

BIN_F:  JNZ BIN_SPEED

       MOV RSPEED,5

BIN_START:

       LEA DX,RBEG; 显示开始产生节拍的提示语

       MOV AH,09H

       INT 21H

        MOV CX,RLEN; 产生节拍次数

       LBIN:

              PUSH CX

              MOV DX,288H; 控制LED指示灯

              MOV AL,0; 先清零

              OUT DX,AL

              MOV AL,00000100B; 强拍,L1亮

              OUT DX,AL

              CALL BEEP1; 输出强拍提示音

              MOV AH,86H; 延时

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              MOV DX,288H

              MOV AL,00000010B; 弱拍,L0亮

              OUT DX,AL

              CALL BEEP3; 输出弱拍提示音

              MOV AH,86H; 延时

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              POP CX

              LOOP LBIN

            MOV DX,288H; 全部节拍完成后,LED清零

            MOV AL,00000000B

            OUT DX,AL

       RET

R_BINARY ENDP

;----------------------------------------

;-------------RYTHEM OF TRIPLEX---------------

R_TRIPLEX PROC NEAR

       LEA DX,R4SPEED

       MOV AH,09H

       INT 21H

TRI_SPEED: 

       MOV AH,07H

       INT 21H

       CMP AL,'S'

       JZ TRI_SL

       CMP AL,'F'

       JZ TRI_F

       JMP TRI_SPEED

TRI_SL:  MOV RSPEED,10

       JMP TRI_START

TRI_F:  JNZ TRI_SPEED

       MOV RSPEED,5

TRI_START:

       LEA DX,RBEG

       MOV AH,09H

       INT 21H

        MOV CX,RLEN

       LTRI:

              PUSH CX

              MOV DX,288H

              MOV AL,0

              OUT DX,AL

              MOV AL,00001000B; 强拍,L2亮

              OUT DX,AL

              CALL BEEP1; 强拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

                MOV DX,288H

              MOV AL,00000100B; 弱拍,L1亮

              OUT DX,AL

              CALL BEEP3; 弱拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              MOV DX,288H

              MOV AL,00000010B; 弱拍,L0亮

              OUT DX,AL

              CALL BEEP3; 弱拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              POP CX

              LOOP LTRI

            MOV DX,288H

            MOV AL,00000000B

            OUT DX,AL

       RET

R_TRIPLEX ENDP

;----------------------------------------

;-------------RYTHEM OF QUADRUPLE---------------

R_QUADRUPLE PROC NEAR

       LEA DX,R4SPEED

       MOV AH,09H

       INT 21H

QUA_SPEED:      

       MOV AH,07H

       INT 21H

       CMP AL,'S'

       JZ QUA_SL

       CMP AL,'F'

       JZ QUA_F

       JMP QUA_SPEED

QUA_SL:       MOV RSPEED,10

       JMP QUA_START

QUA_F:  JNZ QUA_SPEED

       MOV RSPEED,5

QUA_START:

       LEA DX,RBEG

       MOV AH,09H

       INT 21H

        MOV CX,RLEN

       LQUA:

              PUSH CX

              MOV DX,288H

              MOV AL,0

              OUT DX,AL

              MOV AL,00010000B; 强拍,L3亮

              OUT DX,AL

              CALL BEEP1; 强拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

                MOV DX,288H

              MOV AL,00001000B; 弱拍,L2亮

              OUT DX,AL

              CALL BEEP3; 弱拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

                MOV DX,288H

              MOV AL,00000100B; 次强拍,L1亮

              OUT DX,AL

              CALL BEEP2; 次强拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              MOV DX,288H

              MOV AL,00000010B; 弱拍,L0亮

              OUT DX,AL

              CALL BEEP3; 弱拍提示音

              MOV AH,86H

              MOV CX,RSPEED

              MOV DX,0

              INT 15H

              POP CX

              LOOP LQUA

            MOV DX,288H

            MOV AL,00000000B

            OUT DX,AL

       RET

R_QUADRUPLE ENDP

;----------------------------------------           

             

;------------------BEEP1----------------

BEEP1 PROC NEAR;强拍提示音,高频  

       PUSH CX

       PUSH BX

      

       MOV AL,10110110B; 微机8253计数器2方式3,16位二进制计数

       OUT 43H,AL; 微机8253端口地址为40H~43H

        MOV AX,298; 计数初值1.19MHz/4KHz=298

       OUT 42H,AL

       MOV AL,AH

       OUT 42H,AL

       IN AL,61H; 读微机8255A PB口

       MOV AH,AL; 将微机8255APB口数据暂存

       OR AL,03H; 使微机8255PB口PB1(相与OUT2),PB0(GATE2)均为1

       OUT 61H,AL; 打开GATE2,使OUT2输出至扬声器

       MOV CX,0

       MOV BL,40

BEEP_DELAY1:            ; 延时出声

       LOOP BEEP_DELAY1

       DEC BL

       JNZ BEEP_DELAY1

       MOV AL,AH; 恢复微机8255A的PB口原值,停止发声

       OUT 61H,AL

       POP BX

       POP CX

       RET

BEEP1 ENDP

;---------------------------------------

;------------------BEEP2----------------

BEEP2 PROC NEAR;次强拍提示音,次高频

       PUSH CX

       PUSH BX

      

       MOV AL,10110110B

       OUT 43H,AL

        MOV AX,595; 计数初值1.19MHz/2KHZ=595

       OUT 42H,AL

       MOV AL,AH

       OUT 42H,AL

       IN AL,61H

       MOV AH,AL

       OR AL,03H

       OUT 61H,AL

       MOV CX,0

       MOV BL,40

BEEP_DELAY2:

       LOOP BEEP_DELAY2

       DEC BL

       JNZ BEEP_DELAY2

       MOV AL,AH

       OUT 61H,AL

       POP BX

       POP CX

       RET

BEEP2 ENDP

;---------------------------------------

;------------------BEEP3----------------

BEEP3 PROC NEAR; 弱拍提示音,低频   

       PUSH CX

       PUSH BX

      

       MOV AL,10110110B

       OUT 43H,AL

       MOV AX,1190; 计数初值1.19MHZ/1KHZ=1190

       OUT 42H,AL

       MOV AL,AH

       OUT 42H,AL

       IN AL,61H

       MOV AH,AL

       OR AL,03H

       OUT 61H,AL

       MOV CX,0

       MOV BL,40

BEEP_DELAY3:

       LOOP BEEP_DELAY3

       DEC BL

       JNZ BEEP_DELAY3

       MOV AL,AH

       OUT 61H,AL

       POP BX

       POP CX

       RET

BEEP3 ENDP

;---------------------------------------

;--------------PIANO---------------------

PIANO PROC NEAR

       GETKEY:

              MOV AH,07H; 读入按键

              INT 21H

              CMP AL,1BH

              JNE LC  ; 如果不是<Esc>则开始对按键进行判断

              MOV AH,00H; 如果是<Esc>则恢复正常显示

              MOV AL,03H

              INT 10H

              MOV WORD PTR[DI],0FFFFH; 在缓冲区结尾处标志

              JMP MAINMENU; 回到主菜单

       LC:               ; 对do判断

              CMP AL,'1'

              JNE L_C; 如果不是do,则继续判断

              MOV BX,00H; 如果是do,则对频率数组指针偏移量赋值

              MOV CX,72; 键位置的x坐标

              MOV DX,116; 键位置的y坐标

              MOV COLOR1,7; 键按下的颜色

              MOV COLOR2,8; 键恢复的颜色

              MOV WID,11; 键的宽度

              MOV LEN,3; 键的长度等进行赋值

              JMP PLAY; 然后开始发声

       L_C:              ; 对升do判断,以下同理

             CMP AL,'2'

             JNE LD

            MOV BX,0002H

            MOV CX, 80

             MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       LD:

            CMP AL,'3'

            JNE L_D

            MOV BX,04H

            MOV CX, 84

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       L_D:

            CMP AL,'4'

            JNE L_E

              MOV BX,06H

            MOV CX, 92

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       L_E:

            CMP AL,'5'

            JNE LF

            MOV BX,08H

            MOV CX, 96

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       LF:

            CMP AL,'6'

            JNE L_F

            MOV BX,0AH

            MOV CX, 108

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       L_F:

            CMP AL,'7'

            JNE LG

            MOV BX,0CH

            MOV CX, 116

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       LG:

            CMP AL,'8'

            JNE L_G

            MOV BX,0EH

            MOV CX, 120

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       L_G:

            CMP AL,'9'

            JNE LA

            MOV BX,10H

            MOV CX, 128

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

              MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       LA:

            CMP AL,'0'

            JNE L_A

            MOV BX,12H

            MOV CX, 132

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       L_A:

            CMP AL,'-'

            JNE LB

            MOV BX,14H

             MOV CX, 140

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       LB:

            CMP AL,'='

            JNE HC

            MOV BX,16H

            MOV CX, 144

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       HC:               ; 对高音部分的判断

            CMP AL,'Q'

            JNE H_C

            MOV BX,18H

            MOV CX, 156

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       H_C:

            CMP AL,'W'

            JNE HD

            MOV BX,1AH

            MOV CX, 164

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       HD:

            CMP AL,'E'

            JNE H_D

            MOV BX,1CH

            MOV CX, 168

            MOV DX, 116

             MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       H_D:

            CMP AL,'R'

            JNE HE

            MOV BX,1EH

            MOV CX, 176

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       HE:

            CMP AL,'T'

            JNE HF

            MOV BX,20H

            MOV CX, 180

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       HF:

            CMP AL,'Y'

            JNE H_F

             MOV BX,22H

            MOV CX, 192

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       H_F:

            CMP AL,'U'

            JNE HG

            MOV BX,24H

            MOV CX, 200

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       HG:

            CMP AL,'I'

            JNE H_G

            MOV BX,26H

            MOV CX, 204

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       H_G:

            CMP AL,'O'

            JNE HA

            MOV BX,28H

            MOV CX, 212

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

              JMP PLAY

       HA:

            CMP AL,'P'

            JNE H_A

            MOV BX,2AH

            MOV CX, 216

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       H_A:

            CMP AL,'['

            JNE HB

            MOV BX,2CH

            MOV CX, 224

            MOV DX, 101

            MOV COLOR1, 0

            MOV COLOR2, 8

            MOV WID, 7

            MOV LEN, 2

            JMP PLAY

       HB:

            CMP AL,']'

            JNE FAULT1

            MOV BX,2EH

            MOV CX, 228

            MOV DX, 116

            MOV COLOR1, 7

            MOV COLOR2, 8

            MOV WID, 11

            MOV LEN, 3

            JMP PLAY

       FAULT1:

            JMP GETKEY

       PLAY:

              CALL KEYDOWN; 画出键按下的图样

              PUSH BX

              PUSH CX

              PUSH DX

              MOV DX,288H; 发声

              MOV AL,1

              OUT DX,AL

              MOV [DI],BX; 存储频率(数组偏移量)

              INC DI

              INC DI

             

              MOV AL,00110110B; 8253初始化,计数器0,读写16位

              MOV DX,283H    ; 工作方式3,二进制计数

             OUT DX,AL

              MOV AX,[BX+SI]; 赋初值,即设定频率

              MOV DX,280H

              OUT DX,AL

              MOV AL,AH

              OUT DX,AL

              MOV DX,283H

              MOV AL,01010110B;8253初始化,计数器1,低8位读写

              OUT DX,AL;工作与方式3,二进制计数

             

              MOV DX,281H;输出计数器初值,控制向DAC0832写入的频率

              MOV AL,32

              OUT DX,AL

              MOV BX,00H; 开始记录按键时长

       PBEG:

              PUSH SI

              LEA SI,SIN; 输出一个周期的正弦波形

              MOV CX,32

       L0:    

              WAIT1:

                     MOV DX,2B0H

                     MOV AL,[SI]

                     OUT DX,AL; 取得正弦量化数值,送入DAC

                     MOV DX,28AH

                     IN AL,DX

                     CMP AL,01H; 分频控制信号的正半周期

                     JZ WAIT1

              INC SI

              WAIT2:

                     MOV DX,2B0H

                     MOV AL,[SI]

                     OUT DX,AL; 取得正弦量化数值,送入DAC

                     MOV DX,28AH

                     IN AL,DX

                     CMP AL,00H; 分频控制信号的负半周期

                     JZ WAIT2

              INC SI

              LOOP L0

              POP SI

              INC BX; 即输出一个周期的正弦波形,记录时长有一个增量

       HOLD:

              IN AL,60H

              TEST AL,80H

              JZ PBEG; 如果按键未放开,继续记录

             

              MOV DS:[DI],BX; 存储按键时长

              INC DI

              INC DI

              MOV AX,BUFFER; 缓冲区指针后移

              INC AX

              INC AX

              INC AX

              INC AX

              MOV BUFFER,AX

              MOV DX,288H; 停止发声

              MOV AL,0

              OUT DX,AL

              MOV DX,2B0H; DAC输入为零,不发声

              MOV AL,0

              OUT DX,AL

       POP DX

       POP CX

       POP BX

       CALL KEYUP; 画出键恢复的图样

       JMP GETKEY

       RET

PIANO ENDP

;--------------KEYDOWN-------------------

KEYDOWN PROC NEAR

       PUSH AX

       PUSH BX

       PUSH CX

       PUSH DX

       PUSH SI

       PUSH DI

      

       MOV SI,0

       MOV DI,0

       MOV AH,0CH

       MOV AL,COLOR1; 确定图样颜色

       DOWN:

              INT 10H

              INC DX

              INC DI

              CMP DI,LEN; 长度方向画完了吗?

              JNE DOWN; 没画完则继续

              SUB DX,LEN

              MOV DI,0

              INC CX

              INC SI

              CMP SI,WID; 宽度方向画完了吗?

              JNE DOWN; 没画完则继续

       POP DI

       POP SI

       POP DX

       POP CX

       POP BX

       POP AX

       RET

KEYDOWN ENDP

;---------------KEYUP---------------------------

KEYUP PROC NEAR

       PUSH AX

       PUSH BX

       PUSH CX

       PUSH DX

       PUSH SI

       PUSH DI

      

       MOV SI,0

       MOV DI,0

       MOV AH,0CH

       MOV AL,COLOR2; 确定图样颜色

       UP:

              INT 10H

              INC DX

              INC DI

              CMP DI,LEN; 长度方向画完了吗?

              JNE UP; 没画完则继续

              SUB DX,LEN

              MOV DI,0

              INC CX

              INC SI

              CMP SI,WID; 宽度方向画完了吗?

              JNE UP; 没画完则继续

       POP DI

       POP SI

       POP DX

       POP CX

       POP BX

       POP AX

       RET

KEYUP ENDP

;-------------------DRAW----------------------

DRAW PROC NEAR

       PUSH AX

       PUSH BX

       PUSH CX

       PUSH DX

       PUSH SI

       PUSH DI

      

       MOV AX,DATA; 段寄存器初始化

       MOV DS,AX

      

       MOV AH,0; 设置屏幕显示为320X200

       MOV AL,0DH; 彩色图形(EGA)

       INT 10H

       MOV SI,0; 从第一个像素开始

       MOV CX,66; 列

       MOV DX,62; 行

       LEA BX,KEYBOARD

       PART1:

              MOV DI,[BX+SI]; 取像素值

              MOV AX,DI

             

              MOV AH,0CH

              INT 10H

              INC DX

      

              CMP DX,82; 一行画完了吗?

              JNE PART1; 若没有则继续

      

              MOV DX,62; 画下一行

              INC SI

              INC CX

              CMP CX,245; 所有的行都画完了吗?

              JNZ PART1; 若没有则继续

       MOV CX,66

       MOV DX,82

       LEA BX,KEYBOARD; 现在SI=167

       PART2:

              MOV DI,[BX+SI]

              MOV AX,DI

             

              MOV AH,0CH

              INT 10H

              INC DX

              CMP DX,101

              JNE PART2

             

              MOV DX, 82

            INC SI

            INC CX

            CMP CX, 245

            JNZ PART2

       MOV CX, 66

     MOV DX, 101

     LEA BX, KEYBOARD

       PART3:

            MOV DI,[BX+SI]

            MOV AX, DI

            MOV AH, 0CH

            INT 10H

            INC DX

            CMP DX, 103

            JNE PART3

            MOV DX, 101

            INC SI

            INC CX

            CMP CX, 245

            JNZ PART3

       MOV CX, 66

     MOV DX, 103

     LEA BX, KEYBOARD

       PART4:

            MOV DI, [BX+SI]

            MOV AX, DI

            MOV AH, 0CH

            INT 10H

            INC DX

            CMP DX, 116

            JNE PART4

            MOV DX, 103

            INC SI

            INC CX

            CMP CX, 245

            JNZ PART4

       MOV CX, 66

     MOV DX, 116

     LEA BX, KEYBOARD

       PART5:

            MOV DI, [BX+SI]

            MOV AX, DI

            MOV AH, 0CH

            INT 10H

            INC DX

            CMP DX, 119

            JNE PART5

              MOV DX, 116

            INC SI

            INC CX

            CMP CX, 245

            JNZ PART5

       POP DI

       POP SI

       POP DX

       POP CX

       POP BX

       POP AX

       RET

DRAW ENDP

CODE ENDS

END START

更多相关推荐:
电子琴实验报告

电子琴实验报告电子琴实验报告一实验目的1学习使用AT89S52单片机的功能进行单片机编程实现键盘演奏音乐的功能进一步加深对于单片机功能实现过程的理解强化单片机编程的能力2设计实现各种功能包括对音乐的录音以及回访...

小键盘实现电子琴实验报告

小键盘实现电子琴实验报告小键盘实现电子琴实验报告学生13410801房皓13410803张明13410802张耀荣任课教师李济生一实验目的1加强对8253和8255相关知识以及使用的方法的理解掌握2掌握用软件方...

电子琴的实验报告

单片机课程设计设计题目电子琴指导老师苏参与实验者moxiaoxiao专业统本电信0801地点3楼北楼605电子琴一设计目的1培养综合运用知识的能力2朋友查阅资料使用工程设计标准及编写设计文档的能力3掌握单片机应...

VHDL电子琴实验报告

大连理工大学本科实验报告题目电子琴课程名称数字电路课程设计学院系电子信息工程专业电子信息工程班级学生姓名学号完成日期成绩20xx年12月08日题目1设计要求1有两种模式可供选择分别为弹奏模式和自动演奏模式2在弹...

FPGA硬件电子琴电路设计实验报告

FPGA实验报告题目硬件电子琴电路设计一实验目的学习利用数控分频器设计硬件电子琴实验二实验原理及内容主系统由3个模块组成顶层设计文件中包含三个功能模块Speakerav和ToneTabavNoteTabsv模块...

创新实验电子琴实验报告

山东科技大学电工电子实验教学中心创新性实验研究报告实验项目名称专题姓名学号姓名X学号X手机X指导教师及职称赵洪亮开课学期20xx至20xx学年2学期提交时间20xx年6月28日三实验场地及仪器设备和材料六实验心...

单片机创新实验报告--基于单片机的电子琴电路设计

LiaoningNormalUniversity开放实验室项目研究论文题目基于单片机的电子琴电路设计学院物理与电子技术学院专业电子信息工程班级序号学号学生姓名指导教师20xx年12月基于单片机的电子琴电路设计学...

电子琴实验报告

电子琴实验报告本次试验运用AT89S52单片机芯片的定时器中断功能用P10IO口输出不同的脉冲给蜂鸣器使蜂鸣器在不同的频率下工作实现发出不同的音调的效果通过P0口控制16位矩阵键盘使用P0口的P00P03控制键...

电子琴实验报告

电子系统设计创新实验报告题目基于单片机系统的简易电子琴的设计与实现学生姓名严娅叶帅殷玉杰学生学号101234153101234158101234161专业名称电子信息工程指导教师肖永军20xx年11月18日设计...

齐兴甫 106876 电子琴实验报告

20xx年秋河北工业大学计算机硬件技术基础开放性实验报告土木交运C101姓名齐兴甫学号106876成绩学院班级实验组号同组人夏泽民马晓静刘玉飞敖瀚波电子琴实验设计报告一基本功能1具有一般演奏功能利用所给键盘的1...

简易电子琴实验

哈尔滨理工大学单片机原理及接口技术课程设计报告设计题目简易电子琴实验专业电机与电器班级电机101姓名刘国生学号1030350111单片机原理及接口技术课程设计任务书课题描述随着社会发展计算机硬件技术越来越多的应...

实验一 多功能电子琴实验报告

题目多功能电子琴设计课程复杂电子线路综合设计专业电子信息科学与技术班级电子信息学号姓名指导老师完成日期目录1引言2设计要求21基本功能22扩展功能111113设计方案31多功能电子琴的功能介绍132电子琴的主要...

电子琴实验报告(29篇)