📄 music125.asm
字号:
ORG 0000H
LJMP MAIN
ORG 0003H ;外部中断0
LJMP SERV_INT0
ORG 000BH
LJMP T0_INT ;T0中断入口
ORG 001BH
LJMP T1_INT ;T1中断入口
MAIN: MOV SP,#2FH
MOV TMOD,#1H ;初始化
MOV TH1,#9CH ;T150ms初值
MOV TL1,#57H
MOV 7AH,#1H ;显示缓冲区
MOV 7BH,#2H
MOV 7CH,#3H
MOV 7DH,#4H
MOV 7EH,#5H
MOV 7FH,#6H
MOV 80H,#14H ;设置发声1s,即T1中断20次
CLR 21H.0 ;清标志位
MOV DPTR,#3FFFH ;8255命令字地址
MOV A,#88H ;PA输出,PB输出,PC0-PC3输出,PC4-PC7输入
MOVX @DPTR,A
SETB EA ;中断设置
SETB ET0
SETB ET1
SETB EX0
SETB IT0 ;边沿触发方式
DISPLAY:MOV R0,#7AH ;缓冲区首地址
MOV R1,#1H ;选通LED
MOV R2,#6H ;字形码个数
LOOP: ;**************奏乐代码段***********************
JNB 21H.0,NEXT ;按键一次,发声一次
CLR 21H.0 ;--------------方案一:键释放后才发声-----------
MOV A,7AH ;取音符
LCALL TONE ;设置频率初值
SETB TR0
SETB TR1 ;启动定时器,开始发声
;***********************************************
NEXT: ;**************显示代码段***********************
MOV A,@R0
MOV DPTR,#TAB
MOVC A,@A+DPTR ;取字形码
MOV DPTR,#3FFCH ;PA口
MOVX @DPTR,A ;输出字形
MOV DPTR,#3FFDH ;PB口
MOV A,R1
MOVX @DPTR,A ;选通第一个LED
INC R0 ;下一个字形
MOV A,R1
RL A
MOV R1,A ;下一个LED
LCALL DELAY100MS ;延时
DJNZ R2,LOOP ;循环扫描
LJMP DISPLAY
RET
TAB: ;字形码表
DB 0C0H,0F9H,0A4H,0B0H,99H ;0,1,2,3,4
DB 92H,82H,0F8H,80H,90H ;5,6,7,8,9
DB 88H,83H,0C6H,0A1H,86H ;A,B,C,D,E
DB 8EH,0BFH,8CH,0FFH ;F,-,P,暗
FREQ_TAB: ;音符频率初值表
DB 0F1H,17H,0F2H,0A6H,0F4H,29H,0F4H,0D6H,0F5H,08H
DB 0F7H,1FH,0F8H,17H
DB 0F8H,8BH,0F9H,5BH,0FAH,14H,0FAH,6BH,0FBH,04H
DB 0FBH,8FH,0FCH,0BH
TONE: SUBB A,#1H ;设置频率初值子程序
RL A ;调整偏移量
PUSH A ;保存A值
MOV DPTR,#FREQ_TAB
MOVC A,@A+DPTR
MOV TH0,A ;设置TH0
POP A
INC A ;取下个字节
MOVC A,@A+DPTR
MOV TL0,A ;设置TL0
RET
T0_INT: CPL P3.4 ;T0中断服务程序
RETI
T1_INT: DJNZ 80H,CON ;判断发声时间
CLR TR0 ;发声时间到,关闭T0
MOV 80H,#14H
CON: MOV TH1,#9CH ;重装T1C初值,此音符继续发声
MOV TL1,#57H
ENDT1: RETI
SERV_INT0:
SETB RS0
SETB RS1
PUSH ACC
PUSH DPL
PUSH DPH
LCALL DELAY10MS ;前沿消抖
LCALL KEYDOWN ;判断是否仍为按下状态
JZ ENDINT0
MOV R0,#0FEH ;列线轮流置0
MOV R1,#0H ;列号
MOV R2,#0H ;行号
MOV DPTR,#3FFEH ;PC口
COLU: MOV A,R0
ANL A,#0FH ;屏蔽高4位,行线状态
MOVX @DPTR,A ;置列线状态
MOVX A,@DPTR ;读取行线状态
ORL A,#0FH ;屏蔽低4位,列线状态
CPL A ;状态取反
PUSH ACC
MOV A,R0
RL A
MOV R0,A ;下条列线置0
POP ACC
JNZ LINE ;行线不全为0则有键按下,转判断行
INC R1 ;列号加1
AJMP COLU ;继续判断列????????????!!!!!!!!!!!
LINE: CLR C ;清进位位
RLC A ;(行线)状态带进位左移
JC DONE ;进位位为1则此行有键按下
PUSH ACC
MOV A,R2
ADD A,#04H ;行号加4,判断下一行
MOV R2,A
POP ACC
SJMP LINE ;??????????????!!!!!!!!!
DONE: MOV A,#0H ;清A
ADD A,R1
ADD A,R2 ;键号=行号+列号
PUSH ACC ;保存键号
;----------方案二:按键期间发声-----------------
;CLR EA ;关总中断
;LCALL TONE ;设置频率初值
;SETB EA ;开总中断
;SETB TR0 ;启动定时器,开始发声
;---------------------------------------------------------
WAIT: LCALL DELAY10MS ;后沿消抖
LCALL KEYDOWN ;判断键是否释放
JNZ WAIT ;等待键释放
;CLR TR0 ;--------------方案二 键释放就停止发声---------
SETB 21H.0 ;--------------方案一 键释放后才发声-----------
POP ACC ;取A值
MOV 7AH,A ;字形码送入显示缓冲区
MOV 7BH,A
MOV 7CH,A
MOV 7DH,A
MOV 7EH,A
MOV 7FH,A
ENDINT0:POP DPH
POP DPL
POP ACC
CLR RS0
CLR RS1
RETI
KEYDOWN:MOV DPTR,#3FFEH ;PC口
MOV A,#0H ;列线全置0
MOVX @DPTR,A
MOVX A,@DPTR ;读取行线状态
ORL A,#0FH ;屏蔽列线状态
CPL A ;状态取反,行线不全为0则有键按下
RET
DELAY10MS:
MOV R4,#64H
LOOP1: MOV R5,#64H
DJNZ R5,$
DJNZ R4,LOOP1
RET
DELAY100MS:
MOV R6,#010H
LOOP2: MOV R7,#064H
DJNZ R7,$
DJNZ R6,LOOP2
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -