⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dianziqin.asm

📁 利用PC键盘和CRT显示器设计一个电子琴
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;载入键在屏幕上的位置

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)

       CALL SCAN_TUNE                          ;判断是否是C/D调选择键

       CALL FREQ_CHANGE                     ;判断是否按下频率改变键:(+/- 符号)

       CMP AH,01H                                    ;是否是结束键

       JNE FLAG_SCAN                      ;若不是继续检测

       CALL EXIT                                      ;若是则退出

 

FLAG_SCAN:                                          

       MOV AH,02H                                   ;读键盘状态字节

       INT 16H 

       MOV DH,AL                                    ;判断是否是右shift键

       AND DH,01H

    CMP DH,01H    

    JE SLOW                                         ;是则进行低音处理

       MOV DH,AL                                    ;不是判断是否是左shift键

       AND DH,02H

       CMP DH,02H  

       JE SHGH                                          ;是则进行高音处理

       JMP SMID                                        ;都不是进行中音处理

 

SLOW:                                                    ;低音处理

       MOV AUDIO,1                                 

       MOV KEYFLAG,0

       JMP KEY_1                                      ;跳转到音键处理

SHGH:                                                    ;高音处理

       MOV AUDIO,3

       MOV KEYFLAG,2

       JMP KEY_1                                      ;跳转到音键处理

SMID :                                                  ;中音处理

       MOV AUDIO,2

       MOV KEYFLAG,1

 

KEY_1:

       CMP DL,4FH                                    ;是否是1

       JNE KEY_2                                       ;继续判断 

       MOV KEYNUM,0                              ;不是则保存标志

       JMP SCAN_END                               ;键扫描结束

KEY_2:  

       CMP DL,50H                                    ; 是否是2

       JNE KEY_3

       MOV KEYNUM,2

       JMP SCAN_END

KEY_3:

       CMP DL,51H                                    ; 是否是3

       JNE KEY_4

       MOV KEYNUM,4

       JMP SCAN_END

KEY_4:  

       CMP DL,4BH                             ; 是否是4

       JNE KEY_5

       MOV KEYNUM,6

       JMP SCAN_END

KEY_5:

       CMP DL,48H                                    ; 是否是5

       JNE KEY_6

       MOV KEYNUM,8

       JMP SCAN_END

KEY_6:

    CMP DL,4DH                                 ; 是否是6

       JNE KEY_7

       MOV KEYNUM,10

       JMP SCAN_END

KEY_7:

       CMP DL,47H                                    ; 是否是7

       JNE SCAN_END

       MOV KEYNUM,12

SCAN_END:

       RET

SCAN_KEY ENDP

 

SCAN_SONG PROC NEAR

;判断是否是自动播放键(键1~5),并保存标志变量(song)

;IN: AH    键扫描码

       PUSH AX

       MOV SONG,100                                       ;赋初始值

       CMP AH,3BH                                    ;与1比较

       JB  SONG_END                                      ;小于1则结束

       CMP AH,3FH                                    ;与5比较

       JA SONG_END                                        ;大于则结束

       SUB AH,3Bh                                             ;转换成1~5

       MOV AL,AH

       MOV AH,00H

       MOV SONG,AX                                       ;存入标志码

SONG_END:

       POP AX         

       RET

SCAN_SONG ENDP

 

PLAY_SONG PROC NEAR

;选择并播放音乐

PUSH BP

       PUSH SI

       PUSH BX

       PUSH DI

       PUSH AX

 

       CMP SONG,01H                                       ;判断是否是歌1

       JNE GO2                                                 ;不是继续判断

       CALL SONG_LIGHT_OFF               ;灯1~5灭

       DRAW 247,42,251,46,0EH                        ;灯1亮

       LEA BP,MUS_TIME1                               ;载入延时数据首地址

       LEA SI,MUS_FREQ1                               ;载入频率数据首地址

       JMP FREQ                                              

GO2:

       CMP SONG,02H                                       ;判断是否是歌2

       JNE GO3

       CALL SONG_LIGHT_OFF

       DRAW 253,42,257,46,0EH

       LEA BP,MUS_TIME2

       LEA SI,MUS_FREQ2

       JMP FREQ

GO3:

       CMP SONG,03H                                              ;判断是否是歌3

       JNE GO4

       CALL SONG_LIGHT_OFF

       DRAW 259,42,263,46,0EH

       LEA BP,MUS_TIME3

       LEA SI,MUS_FREQ3

       JMP FREQ

 

GO4:

       CMP SONG,04H                                              ;判断是否是歌4

       JNE GO5

       CALL SONG_LIGHT_OFF

       DRAW 265,42,269,46,0EH

       LEA BP,MUS_TIME4

       LEA SI,MUS_FREQ4

       JMP FREQ

 

GO5:

       CMP SONG,05H                                              ;判断是否是歌5

       JNE FREQ

       CALL SONG_LIGHT_OFF

       DRAW 271,42,275,46,0EH

       LEA BP,MUS_TIME5

       LEA SI,MUS_FREQ5

 

FREQ:

       MOV AH,01H                                                 ;读键盘缓冲区字符

       INT 16H

       CMP AH,1CH                                                 ;是否是Enter键

       JNZ CONTINUE                                              ;不是继续

       JMP PLAY_END                                             ;是结自动播放

CONTINUE:

       MOV AH,0CH                                                ;清除键盘缓冲区字符

       MOV AL,06H

       INT 21H

       MOV DI,[SI]

       CMP DI,-1                                                      ;判断结束否

    JE  PLAY_END                                             

       MOV BX,[BP]

       CALL GEN_AUTO                                          ;发声

       ADD SI,2

       ADD BP,2                                                       ;下一频率

       JMP FREQ

PLAY_END:

       CALL SONG_LIGHT_OFF

       POP AX

       POP DI

       POP BX

       POP SI

       POP BP

       RET 

PLAY_SONG ENDP

LOAD_AUDIO PROC NEAR

;C\D调及对应的低、中、高频率分别载入

;OUT:BX

;IN:TUNE,AUDIO

TUNE_D:                                                        ;D大调判断

       CMP TUNE,'D'

       JNZ TUNE_CL                                         ;不是判断是否是C调

TUNE_DL:

       CMP AUDIO,1                                         ;低频判断

       JNE TUNE_CM

       LEA BX,LOWDD

       JMP AUDIO_END

TUNE_DM:

       CMP AUDIO,2                                         ;中频判断

       JNE TUNE_CH

       LEA BX,MIDD

       JMP AUDIO_END

TUNE_DH:

       LEA BX,HGHD                                        ;高频判断

       JMP AUDIO_END

 

TUNE_CL:                                                      ;C调处理

       CMP AUDIO,1

       JNE TUNE_CM

       LEA BX,LOWD

       JMP AUDIO_END

TUNE_CM:

       CMP AUDIO,2

       JNE TUNE_CH

       LEA BX,MID

       JMP AUDIO_END

TUNE_CH:

       LEA BX,HGH

 

AUDIO_END:

       RET

LOAD_AUDIO ENDP

 

SCAN_TUNE PROC NEAR

;C\D调判断及其状态在屏幕上的显示

;IN:DL  键盘扫描码

;OUT:TUNE

       CMP DL,2EH                                    ;判断是C否

       JNZ NEXT_D                                    ;不是则判断是D否

       MOV TUNE,'C'

       DRAW 55,38,60,41,0EH                           ;关D灯

       DRAW 65,38,70,41,0AH                           ;开C灯

       JMP TUNE_END                                       ;结束

NEXT_D:

       CMP DL,20H                                           ;判断D否

       JNZ TUNE_END

       MOV TUNE,'D'

       DRAW 55,38,60,41,0AH                           ;开D灯

       DRAW 65,38,70,41,0EH                           ;关C灯

TUNE_END:

       RET

SCAN_TUNE ENDP

 

SHOW_TEXT PROC NEAR

;在屏幕上显示字符

       LEA DI,TEXT                                          ;载入字符串首地址

       MOV DH,[DI]                                         ;赋行值

       INC DI                                                    ;取得列

       MOV DL,[DI]                                          ;赋列值

       MOV START_COL,DL                            ;保存开始列

       MOV AH,2                                              ;设置光标位置

       MOV BH,0                                              ;0页

       INT 10H

       INC DI                                                    ;取得颜色值

       MOV BL,[DI]                                          ;赋颜色值

CHAR_WRITE:

       INC DI                                                    ;取得要显示的字符

       MOV AL,[DI]

       CMP AL,0FFH                                         ;行结束否

       JE BUMP_ROW                                      ;下一行

       CMP AL,0                                                ;结束否

       JZ END_TEXT

       CALL SHOW_CHAR                              ;显示字符

       JMP CHAR_WRITE                                       ;下一个字符

       END_TEXT:

       RET

BUMP_ROW:

       INC DH                                                          ;下一行

       MOV DL,START_COL                                   ;赋开始列值

       MOV AH,2                                                     ;设光标位置

       MOV BH,0

       INT 10H

       JMP CHAR_WRITE

SHOW_TEXT ENDP

 

SHOW_CHAR PROC NEAR

;显示字符

MOV AH,9                                                     ;显示字符

       MOV BH,0                                                     ;0页

       MOV CX,1

       INT 10H

       INC DL                                                          

       MOV AH,2                                                     ;设置光标位置

       MOV BH,0                                                     ;0页

       INT 10H

       RET

SHOW_CHAR ENDP

 

INIT PROC NEAR

;初始化屏幕:画琴键

MOV AX,DATA

    MOV DS,AX

 

       MOV AH,0                                                     ;设置屏幕

    MOV AL,0DH

       INT 10H

    MOV AH,0BH

    MOV BH,0

    MOV BL,00H                                                 ;背景色

    INT 10H

 

       CALL SHOW_TEXT                                       ;显示字符串

       DRAW 45,30,285,94,05H     

       DRAWSQRE 45,30,285,94,0DH

       DRAWSQRE 49,48,280,49,00H 

       

       DRAW 55,38,60,41,0EH                                  ;C调灯

       DRAW 65,38,70,41,0AH                                  ;D调灯

       CALL SONG_LIGHT_OFF                      ;自动播放歌指示灯关

 

       LEA SI,ST_LX                                                ;画21个白色键

    LEA DI,ED_LX

    MOV CX,21

INIT_DRAW:

    DRAW [SI],ST_Y,[DI],ED_Y,0FH

    DRAW [SI],90,[DI],93,07H                             ;阴影

    ADD SI,2

    ADD DI,2

    LOOP INIT_DRAW     

 

    LEA SI,BT_X                                           ;画15个黑色键

    LEA DI,BD_X

    MOV CX,15

INIT_BLOCK:

    DRAW [SI],BT_Y,[DI],BD_Y,00H

    ADD SI,2

    ADD DI,2

    LOOP INIT_BLOCK   

 

       RET 

INIT ENDP

SONG_LIGHT_OFF PROC NEAR

;关闭灯1~5

       DRAW 271,42,275,46,09H

       DRAW 265,42,269,46,09H

       DRAW 259,42,263,46,09H

       DRAW 253,42,257,46,09H

       DRAW 247,42,251,46,09H

       

       RET

SONG_LIGHT_OFF ENDP

 

FREQ_CHANGE PROC NEAR

;IN:DL   扫描码

       CMP DELAY_TIME,600

       JB  CHANGE_ADD

       CMP DELAY_TIME,60000

       JA  CHANGE_SUB

       CMP DL,0CH              ;-

       JNZ FREQ_SUB

       ADD DELAY_TIME,500

       DRAW 271,38,274,41,0EH

       JMP CHANGE_END

CHANGE_ADD:

       ADD DELAY_TIME,500

       JMP CHANGE_END

CHANGE_SUB:

       SUB DELAY_TIME,500

       JMP CHANGE_END

FREQ_SUB:

       CMP DL,0DH              ;+

       DRAW 271,38,274,41,0AH

       JNZ CHANGE_END

       SUB DELAY_TIME,500

CHANGE_END:

       RET

FREQ_CHANGE ENDP

 

EXIT PROC NEAR

;程序结束

       MOV AH,4CH

       INT 21H

        RET

EXIT ENDP

CODE ENDS

     END START

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -