📄 elekeyboard.asm
字号:
;;;;;;;;;;;;;;;;;;;;电子琴;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;功能:
; 1.电子琴基本音阶的发生,低音、高音、中音
; 2.播放音乐
; 3.播放音阶时指示灯亮
;-----------------------------------------------------------------
DRAW MACRO START_X,START_Y,END_X,END_Y,COLOR ;画矩形的宏程序
LOCAL DRAW_NEXT
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AH,0CH
MOV AL,COLOR
MOV BH,0
MOV CX,START_X
MOV DX,START_Y
DRAW_NEXT:
INT 10H
INC CX
CMP CX,END_X
JNE DRAW_NEXT
MOV CX, START_X
INC DX
CMP DX,END_Y
JNE DRAW_NEXT
POP DX
POP CX
POP BX
POP AX
ENDM
;--------------------------------------------------------------
DRAWSQRE MACRO START_X,START_Y,END_X,END_Y,COLOR ;画出边框的宏程序
LOCAL ROW_UP,ROW_DOWN,RANK_LEFT,RANK_RIGHT
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
MOV AH,0CH
MOV AL,COLOR
MOV BH,0
MOV CX,START_X
MOV DX,START_Y
ROW_UP: ;画上边沿
INT 10H
INC CX
CMP CX,END_X
JNE ROW_UP
RANK_RIGHT: ;右边沿
INT 10H
INC DX
CMP DX,END_Y
JNE RANK_RIGHT
MOV CX, START_X
MOV SI,END_X
INC SI
ROW_DOWN: ;下边沿
INT 10H
INC CX
CMP CX,SI
JNE ROW_DOWN
MOV DX,START_Y
MOV CX,START_X
RANK_LEFT: ;左边沿
INT 10H
INC DX
CMP DX, END_Y
JNE RANK_LEFT
POP SI
POP DX
POP CX
POP BX
POP AX
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;数据段
DATA SEGMENT
;定义在屏幕绘制字
START_COL DB ? ;存储起始行
TEXT DB 16 ;起始行
DB 2 ;起始列
DB 06H ;字体颜色
DB 0ffh,'WELCOME TO THE PIANO',0ffh ;显示字
DB 0FFH, 'press a to j to piano'
DB 0FFH,0FFH,'press shfit to choose tune',0ffh
db 0ffh,'press 1 to 5 to choose music'
;白色琴键坐标
ST_LX DW 50,61,72,83,94,105,116
ST_MX DW 127,138,149,160,171,182,193
ST_HX DW 204,215,226,237,248,259,270
ST_Y DW 50
ED_LX DW 60,71,82,93,104,115,126
ED_MX DW 137,148,159,170,181,192,203
ED_HX DW 214,225,236,247,258,269,280
ED_Y DW 90
;黑色琴键坐标
BT_X DW 57,68,90,101,112
DW 134,145,167,178,189
DW 211,222,244,254,265
BT_Y DW 50
BD_X DW 64,75,97,108,119
DW 141,152,174,185,196
DW 218,229,251,262,273
BD_Y DW 70
;音乐频率值
LOWD DW 131
LOWDD DW 147,165,175,196,220,247
MID DW 262
MIDD DW 294,330,349,392,440,494
HGH DW 523
HGHD DW 587,659,797,783,879,987,1046
KEYFLAG DB 1 ;标记低(0)、中(1)、高(2)音键
KEYNUM DW 1 ;存储1~7
DELAY_TIME DW 1000 ;延时
SONG DW 100 ;保存所选的自动演奏的曲目
TUNE DW 1 ;标记c
AUDIO DW 1 ;标记低(1)、中(2)、高音(3)
;自动演奏的歌曲频率和延时
MUS_FREQ1 DW 440,392,330,392,523,440,392,440
DW 330,392,440,392,330,262,220,392
DW 330,2 DUP(294),330,2 DUP(392),440,330
DW 294,262,392,330,294,262,220,262,196
DW -1
MUS_TIME1 DW 37,12,3 DUP(25),2 DUP(12),50
DW 25,2 DUP(12 ),2 DUP(25),4 DUP(12 ),50
DW 37 ,12 ,25,2 DUP(12 ),2 DUP(25),50
DW 37 ,5 DUP(12 ),100
MUS_FREQ2 DW 196,262,330,392,330,294,262,262,262,262,220,196,196,196,131,659,392,392,392,440,392,392
DW 294,330,294,262,294,440,392,523,392,392,392,440,392,330,294,262,262,294,220,196,220,523,294,330,294,330,262,262,-1
MUS_TIME2 DW 8,8,16,8,16,5 dup(8),2,2,16,8,8,16,4 dup(8)
dw 2,2,8,2,2,8,8,16,8 dup(8),2,2,16,8,8,2,2,16,8,8,8
MUS_FREQ3 DW 262,262,294,330,330,349,392,440,392,330
DW 392,349,330,294,349,330,294,262
DW 262,262,294,330,330,349,392,440,392,330
DW 392,349,330,294,330,294,262,196
DW 392,349,330,294,196,196,349,330,294,262
DW 392,349,330,294,196,196,349,330,294,262
DW 262,262,294,330,330,349,392,440,392,330
DW 392,349,330,294,330,294,262
DW -1
MUS_TIME3 DW 3 DUP(25,2 DUP(12)),50
DW 2 DUP(25,2 DUP(12),50)
DW 3 DUP(25,2 DUP(12)),50
DW 2 DUP(25,2 DUP(12)),2 DUP (50)
DW 3 DUP(25,2 DUP(12)),50
DW 3 DUP(25,2 DUP(12)),50
DW 3 DUP(25,2 DUP(12)),50
DW 2 DUP(25,2 DUP(12)),50
MUS_FREQ4 DW 262,262,294,330,330,294,262,262,220,196
DW 262,294,330,294,262,294
DW 262,294,330,330,294,294,262,220,220,294,262,262,220,196
DW 196,220,220,262,262,294,294,262,220
DW 294,330,294,262,262,294,262,220,196,220
DW 196,220,262,294,330,392,294,330,262,294,262,220
DW 220,294,247,220,196,196
DW 4 DUP(392),330,392,440,440,392,330
DW 5 DUP(440),392,392,330,294
DW 440,392,440,392,330,294,330,294,262,220
DW 4 DUP(294),262,220,196
DW 2 DUP(440,392),2 DUP(330,294),262,220
DW 3 DUP(294),262,220,392
DW -1
MUS_TIME4 DW 3 DUP(20,10,10),50
DW 20,10,20,10,10,80
DW 20,10,20,10,10,3 DUP(20,10),20,20,80
DW 20,10,10,20,20,20,10,10,40
DW 20,10,20,20,10,5,5,10,10,40
DW 20,10,2 DUP(20,10,10),10,5,5,20
DW 20,20,20,10,10,80
DW 10,20,10,20,10,10,40,10,10,20
DW 8 DUP(10),80
DW 20,10,10,20,20,4 DUP(10),40
DW 15,5,10,10,20,20,80
DW 20,10,10,20,20,4 DUP(10),40
DW 40,20,20,40,40,100
MUS_FREQ5 DW 523,587,659,196,523,659,587,196,247,587,523,523,247
DW 523,523,196,220,523,523,220,196,196,523,659,797,659,523,587,587,-1
MUS_TIME5 DW 11 DUP(20),40,10,10,40,20,20,11 DUP(20),5,5,40
MUS_FREQ6 DW ? ;存储乐曲频率
MUS_TIME6 DW ? ;存储乐曲时间
DATA ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;代码段
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CODE SEGMENT
ASSUME DS:DATA,CS:CODE
MAIN PROC FAR
;主程序
START:
CALL INIT ;调用初始化程序
NEW_SCAN:
CALL SCAN_KEY ;扫描所按下的键
CMP SONG,100 ;判断是否按下了自动播放的歌曲键
JE HAND_PLAY ;若不是,继续判断
CALL PLAY_SONG ;若是,演奏音乐
JMP NEW_SCAN ;演奏结束,重新扫描有无键按下
HAND_PLAY:
CMP KEYNUM,100 ;判断是否手动演奏
JZ NEW_SCAN ;若不是,重新扫描有无键按下
;若是,进行按键处理
PUSH BX
MOV BX,KEYNUM
CALL KEY_DOWN ;在屏幕上显示按下状态
POP BX
CALL LOAD_AUDIO ;判断高低音,并装入对应频率段地址到BX中
PUSH SI
MOV SI,KEYNUM
MOV DI,[BX+SI]
CALL GEN_HAND ;发声
POP SI
PUSH BX
MOV BX,KEYNUM ;在屏幕上显示弹起状态
CALL KEY_UP
POP BX
JMP NEW_SCAN ;重新扫描有无键按下,直到按下ESC键
MAIN ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;手动演奏发声程序
GEN_HAND PROC NEAR
;IN:DI
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV AL,90H ;初始化
MOV DX,28BH
OUT DX,AL
MOV AL,0B6H ;定时器初始化
OUT 43H,AL
MOV DX,12H
MOV AX,348CH
DIV DI
OUT 42H,AL ;定时器送处值
IN AL,61H ;开扬声器
MOV AL,AH
OUT 42H,AL
IN AL,61H
MOV AH,AL
OR AL,3
OUT 61H,AL
WAIT1:
CALL WAITF ;调用延时程序
IN AL,60H
TEST AL,80H ;查询键是否放开
JNZ LED_OFF ;未放开继续查询
JMP WAIT1
LED_OFF:
MOV AL,0 ;放开则关扬声器
OUT 61H,AL
POP DI
POP DX
POP CX
POP BX
POP AX
RET
GEN_HAND ENDP
;------------------------------------------------------------------------
PIANO_DRAW PROC NEAR ;绘制琴键
LEA SI,ST_LX ;载入白色起始点地址
LEA DI,ED_LX ;载入白色结束点地址
MOV CX,21 ;白键数目
NEXT_DRAW:
DRAW [SI],ST_Y,[DI],ED_Y,0FH ;调用宏定义画白键
DRAW [SI],90,[DI],93,07H ;阴影
ADD SI,2 ;下一个键
ADD DI,2
LOOP NEXT_DRAW
LEA SI,BT_X ;载入黑色起始点地址
LEA DI,BD_X ;载入黑色结束点地址
MOV CX,15 ;黑键数目
NEXT_BLOCK:
DRAW [SI],BT_Y,[DI],BD_Y,00H
ADD SI,2
ADD DI,2
LOOP NEXT_BLOCK
RET
PIANO_DRAW ENDP
;----------------------------------------------------------------------
KEY_DOWN PROC NEAR ;键按下时,在屏幕上显示
PUSH SI
PUSH DI
CALL LOAD ;载入所按下键在屏幕上的位置
DRAW [SI+BX],90,[DI+BX],92,0FH
DRAW [SI+BX],92,[DI+BX],94,07H
POP DI
POP SI
RET
KEY_DOWN ENDP
;----------------------------------------------------------------------
KEY_UP PROC NEAR ;键弹起时,恢复正常状态
PUSH SI
PUSH DI
CALL LOAD ;载入所弹起键在屏幕上的位置
DRAW [SI+BX],90,[DI+BX],93,07H ;恢复阴影
DRAW [SI+BX],93,[DI+BX],94,05H ;恢复背景色
POP DI
POP SI
RET
KEY_UP ENDP
;-------------------------------------------------------------------------
LOAD PROC NEAR ;载入键在屏幕上的位置
CMP KEYFLAG,00H ;判断是否是低音键
JNZ LOAD_HGH ;继续判断
LEA SI,ST_LX ;载入低音键起始坐标首地址
LEA DI,ED_LX ;载入低音键结束坐标首地址
JMP LOAD_END ;载入结束
LOAD_HGH:
CMP KEYFLAG,02H ;判断是否是高音键
JNZ LOAD_MID ;继续判断
LEA SI,ST_HX ;载入高音键起始坐标首地址
LEA DI,ED_HX ;载入高音键结束坐标首地址
JMP LOAD_END
LOAD_MID:
LEA SI,ST_MX ;载入中音键起始坐标首地址
LEA DI,ED_MX ;载入中音键结束坐标首地址
LOAD_END:
RET
LOAD ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SCAN_KEY PROC NEAR
;检查按键状态,并存入对应的变量和寄存器
MOV SI,100
MOV DI,100
MOV KEYNUM,100 ;赋初值
MOV AH,0 ;读键盘
INT 16H
MOV DL,AH
CALL SCAN_SONG ;判断是否是自动播放键(大键盘数字键1~5)
CMP AH,01H ;是否是结束键
JNE FLAG_SCAN ;若不是继续检测
CALL EXIT ;若是则退出
FLAG_SCAN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -