汇编课设电子琴

MY8255_A    EQU  0600H
MY8255_B    EQU  0602H
MY8255_C    EQU  0604H                                  
MY8255_MODE EQU  0606H
MY8254_MODE EQU  06C6H
MY8254_A    EQU  06C0H   ;进行宏定义
DATA  	SEGMENT
FREQ_LIST DW 441D,495D,556D,589D,661D,742D,833D,882D,262D,294D,330D,373D,402D,450D,494D,-1D
DATA  	ENDS     ;建立数据段

CODE 	SEGMENT
      	ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
		MOV DS,AX       ;实现段寄存器DS的初始化
 	   MOV DX,MY8255_MODE
MOV AL,81H
OUT DX,AL    ;写8255芯片的控制字,实现工作在方式0,A端口和B端口输出,C端口输入

		MOV DX,MY8254_MODE
		MOV AL,36H
		OUT DX,AL        ;使8254工作在方式3,A口输入,运用计数器0,二进制方式
BEGIN: CALL CCSCAN	     ;扫描
		JNZ INK1         ;有键按下时跳到INK1
		JMP BEGIN        ;没按下时循环执行BEGIN


;确定按下键的位置
INK1:   MOV CH,0FEH     ;确定按下键在第一列
		MOV CL,00H      ;将CL清零
COLUM:  MOV AL,CH
        MOV DX,MY8255_A ;将8255的A口地址赋给DX
		OUT DX,AL       ;将CPU中的AL值送到8255的A口中,即送到x1、x2、x3、x4中
        MOV DX,MY8255_C ;将8255的C口地址赋给DX
		IN AL,DX        ;将C口的值送到AL中 

L1:     TEST AL,01H     ;检验按下键是否在L1
        JNZ L2          ;不是L1则跳到L2
        MOV AL,00H      ;为了后面用来与FREQ_LIST数据段中数对应                                                                                     
		JMP KCODE       ;强制跳转到KCODE

L2:     TEST AL,02H     ;检验按下键是否在L2 
        JNZ L3          ;不是L2则跳到L3
        MOV AL,04H              ;为了后面用来与FREQ_LIST数据段中数对应。
        JMP KCODE               ;强制跳转到KCODE
        
L3:     TEST AL,04H     ;检验按下键是否在L23
        JNZ L4          ;不是L3则跳到L4
        MOV AL,08H              ;为了后面用来与FREQ_LIST数据段中数对应。
        JMP KCODE               ;强制跳转到KCODE
        
L4:     TEST AL,08H     ;检验按下键是否在L4  
        JNZ NEXT        ;不是L4则跳到NEXT
        MOV AL,0CH              ;为了后面用来与FREQ_LIST数据段中数对应。


KCODE:  ADD AL,CL       ;实现AL与CL的无进位加法
        MOV DL,2D                      
        MUL DL          ;将AL乘以2结果保存到AX中
        
PLAY:   MOV SI,OFFSET FREQ_LIST ;使SI指向 FREQ_LIST的首地址
        ADD SI,AX               ;通过SI加AX 实现指针SI的移动
        MOV DX,0FH                     
        MOV AX,4240H            ;被除数为0F4240H
        DIV WORD PTR[SI]        ;除数为SI所指的数据
        MOV DX,MY8254_A         ;将8255的A口地址赋给DX
        OUT DX,AL               ;输出商的低4位
        MOV AL,AH
        OUT DX,AL               ;输出商的高4位
        MOV CX,8D               ;输入计数值CX
        
NEXT3: CALL DALLY              ;调用延时子程序DALLY
       LOOP NEXT3                      ;CX不为0重复执行NEXT3  
        MOV DX,0FH                     
        MOV AX,4240H            ;被除数为0F4240H
        MOV SI ,30D                    
        DIV WORD PTR[SI]        ;除数为SI=30所指的数据
        MOV DX,MY8254_A         ;将8255的A口地址赋给DX
        OUT DX,AL                       
        MOV AL,AH                      
        OUT DX,AL               ;实现静音,结束一个音符的发音
        JMP BEGIN               ;跳转到BEGIN,重复扫描
NEXT:   INC CL                  ;使CL加1,为了后面用来与FREQ_LIST数据段中数对应
	     MOV AL,CH                        
		 TEST AL,08H                      
		 JZ KERR                ;无键按下时跳转到KERR
		 ROL AL,1D              ;向左移位
		 MOV CH,AL
		 JMP COLUM              ;强制跳转到COLUM

KERR:   JMP BEGIN               ;跳到BEGIN重新开始扫描


;键盘扫描子程序
CCSCAN: MOV AL,00H
        MOV DX,MY8255_A  
		 OUT DX,AL              ;使8255芯片A端口输出为0,既使x1、x2、x3、X4为0
        MOV DX,MY8255_C 
        IN  AL,DX               ;将从C端口输入的y1、y2、y3、y4送到AL中
		NOT AL                  ;将AL取反
        AND AL,0FH              ;将AL前4位清零
		RET


;延时子程序
DALLY:  PUSH CX                 ;将CX压栈
        MOV CX,000FH                          
T1:     MOV AX,0009FH
T2:     DEC AX                  ;使AX减1
		JNZ T2                  ;AX不为0重复T2
		LOOP T1                 ;CX不为0重复T1
		POP CX                  ;将CX出栈
		RET
CODE	ENDS                    ;代码段定义结束
END START                       ;程序结束

音符

1

2

3

4

5

6

7

1

2

3

4

5

6

7

1

频率

131

147

165

175

196

220

247

262

294

330

349

392

440

494

523

汇编课设电子琴_第1张图片汇编课设电子琴_第2张图片

你可能感兴趣的:(汇编)