采用汇编语言,设计可以上下切换和暂停的音乐盒。该音乐盒一共有四首midi音乐,分别是《两只蝴蝶》,《祝你平安》、《两只老虎》、《猪八戒背媳妇》,直接上程序。
/******利用汇编语言设计的音乐盒 ******/
//一共有四首歌曲,可以通过下一曲,上一曲调整播放顺序***
//设置了暂停按键************/
//作者ydk,2024.5.9
//******fosc=11.0592MHz******************
/******利用汇编语言设计的音乐盒 ******/
//一共有四首歌曲,可以通过下一曲,上一曲调整播放顺序***
//设置了暂停按键************/
//作者ydksummer,2024.5.9
//******fosc=11.0592MHz******************
JIA BIT P3.2 ;下一曲
JIAN BIT P3.3 ;上一曲
ZT BIT P3.4 ;暂停键
FLAG BIT 21H.0 ;调整标志位
ORG 0000H
AJMP MAIN
ORG 0003H
AJMP INIT0
ORG 000BH
AJMP TIM0
org 0013h
ajmp INIT1
ORG 001BH
AJMP TIM1
ORG 0030H
MAIN:
MOV TMOD,#11H
MOV TL1,#0CDH ;设置定时时间为62ms
MOV TH1,#020H
SETB IT0
SETB EX0
SETB IT1
SETB EX1
SETB EA
SETB ET0
SETB ET1
SETB TR1
MOV R1,#0 ;控制取节拍还是频率
MOV 20H,R1 ;20H保存频率位置,查表求频率
MOV R2,#0 ;保存节拍
mov r7,#0 ;歌曲演奏计数器
MOV DPTR,#TIME ;初始演奏第一首歌曲
MOV R5,DPH //用于保存歌曲的首地址
MOV R6,DPL
SETB TF0 //给T0初始化
LOOP:
ACALL KEYSAN //按键检测,判断是否暂停
JNB F0,ENDLOOP //F0为暂停标志位,没有暂停转
CLR EA //暂停键按下,关闭中断,则调整无效
AJMP LOOP //一直处于暂停状态
ENDLOOP:SETB EA
JNB FLAG, LOOP //没有调整转loop
clr ea
CJNE R7,#00H,GU1
MOV DPTR,#TIME
MOV R5,DPH //保存第一首歌曲首地址
MOV R6,DPL
AJMP LOOP1
GU1: CJNE R7,#01H,GU2
MOV DPTR,#TIME1
MOV R5,DPH //保存第2首歌曲首地址
MOV R6,DPL
AJMP LOOP1
GU2: CJNE R7,#02H,GU3
MOV DPTR,#TIME2
MOV R5,DPH //保存第2首歌曲首地址
MOV R6,DPL
AJMP LOOP1
GU3: CJNE R7,#03H,LOOP
MOV DPTR,#TIME3
MOV R5,DPH //保存第2首歌曲首地址
MOV R6,DPL
AJMP LOOP1
LOOP1:
MOV R1,#0 //歌曲重新开始
MOV 20H,R1
MOV R2,#0
CLR FLAG //清除调整标志位
AJMP LOOP
/******暂停按键******/
KEYSAN:SETB ZT
JB ZT,ENDKEY
JNB ZT,$
CPL F0
ENDKEY:RET
/********************/
/******下一曲按键********/
INIT0:CLR EA //关中断
JB JIA,LP //抖动返回
JNB JIA,$ //等待按键释放
INC R7
SETB FLAG
CJNE R7,#04H,LP
MOV R7,#00H
LP: SETB EA
RETI
/******上一曲按键********/
INIT1:CLR EA //关中断
JB JIAN,LP1 //抖动返回
JNB JIAN,$ //等待按键释放
DEC R7
SETB FLAG
CJNE R7,#0FFH,LP1
MOV R7,#03H
LP1: SETB EA
RETI
TIM0: mov dph,r5
mov dpl,r6
mov a,20h //送音阶地址
movc a,@a+dptr
rl a //地址*2确定音阶定时初值
mov b,a //暂存
mov dptr,#freq //查频率表给T0赋值
movc a,@a+dptr //取高8位初值
jz yy //判断是否是休止符,0为休止符
mov th0,a
mov a,b
inc a //地址加一,取低8位初值
movc a,@a+dptr
mov tl0,a
setb tr0
cpl p2.4 //输出脉冲
ajmp yy1
yy: setb p2.4 //是休止符,停止播放
yy1: reti
TIM1:
MOV TL1,#0CDH ;设置定时时间为62ms
MOV TH1,#020H
cjne r2,#0,nequ //r2用于中断次数,决定每个音节的长短
// mov dptr,#time
mov dph,r5
mov dpl,r6
inc r1 //取节拍时地址加一
mov a,r1
movc a,@a+dptr
rl a //节拍加倍,决定歌曲播放的快慢
mov r2,a
ajmp exit
nequ: djnz r2,exit //判断一个音阶是否结束
inc r1 //取下一个音阶地址加一
mov 20h,r1 //频率位置暂存20h中
mov a,r1
// mov dptr,#time
mov dph,r5
mov dpl,r6
movc a,@a+dptr
cjne a,#0ffh,exit //判断是否为歌曲结束标志
clr ea
lcall delay3s ;延时3s,演奏下一首
INC R7 ;修改曲目计数器
SETB FLAG ;设置调整标志位
CJNE R7,#04H,exit1
MOV R7,#00H
exit1:setb ea
exit:
reti
delay3s:PUSH 30H
PUSH 31H
PUSH 32H
MOV 30H,#22
MOV 31H,#3
MOV 32H,#220
NEXT:
DJNZ 32H,NEXT
DJNZ 31H,NEXT
DJNZ 30H,NEXT
POP 32H
POP 31H
POP 30H
RET
FREQ: DW 0,63777,63970,64021,64216,64361,64489,64603//
DW 64655,64751,64837,64876,64948,65012,65070 //8
DW 65096,65144,65186,65206,65242,65275,65303 //15
//两只蝴蝶
TIME: DB 10,2,9,2,10,8,9,2,10,2,9,2,8,12,6,2,8,2
DB 9,4,10,4,9,2,8,2,6,2,8,2,5,12
DB 10,2,9,2,10,8,9,2,10,2,9,2,8,12,6,2,8,2
DB 9,4,10,4,9,2,8,2,6,2,8,2,5,12
DB 10,2,9,2,10,8,9,2,10,2,9,2,8,12,6,2,8,2
DB 9,4,10,4,9,2,8,2,6,2,8,2,5,4
DB 10,2,12,2,12,8,12,2,13,2,12,2,10,12
DB 9,2,10,2,9,4,10,4,9,2,8,2,6,2,8,2,8,16
DB 12,4,13,2,12,2,15,2,21,2,21,2,20,2,10,2,9,2,9,2,10,2,10,8
DB 10,2,10,2,12,2,13,4,13,4,6,2,10,2,9,2,9,12
DB 10,2,12,2,12,2,10,2,12,4,15,3,14,2,13,2,13,1,14,1,10,4,13,2,13,2,13,1,15,1
DB 13,2,13,1,12,1,10,1,9,1,9,2,10,2,9,2,9,1,10,1
DB 12,8,12,2,12,2,12,1,13,1,13,2,12,2,10,2,9,2,5,4,6,2,8,16,0XFF
//两只老虎
TIME1: db 8,4,9,4,10,4,8,4
db 8,4,9,4,10,4,8,4
db 10,4,11,4,12,8
db 10,4,11,4,12,8
db 12,3,13,1,12,3,11,1,10,4,8,4
db 12,3,13,1,12,3,11,1,10,4,8,4
db 9,4,5,4,8,8
db 9,4,5,4,8,8,0xff
/*** 祝你平安******/
TIME2:
DB 10,2,12,2,12,2,10,1,12,1,12,8 //你的心情
DB 10,2,8,2,8,2,6,1,8,1,8,8 //现在还好吗
DB 10,2,12,2,12,2,13,2,12,8 //你的脸上
DB 9,2,10,2,12,2,9,1,10,1,9,8 //还有微笑吗
DB 10,2,8,2,8,2,6,1,10,1,10,4,0,4,5,1,6,1//人生自古就有
DB 10,2,8,2,8,2,6,1,10,1,10,8 //许多愁和苦
DB 10,2,9,1,9,1,9,2,8,1,6,1,10,1,9,1,9,2,9,4; 请你多一些开心
DB 5,2,12,1,12,1,9,1,10,3,8,8 //少一些烦恼
DB 15,2,15,2,10,2,12,2,12,5,10,1,9,1 //祝你平安哦
DB 8,2,8,2,13,2,12,2,12,8 //祝你平安
DB 13,2,13,2,13,2,8,2,8,4,0,2,6,1,8,1//让那快乐围绕
DB 12,2,9,1,10,1,9,1,10,1,10,1,9,1,9,8//在你身边
DB 15,2,15,2,10,2,12,2,12,5,10,1,9,1 //祝你平安哦
DB 8,2,8,2,13,2,12,2,12,8 //祝你平安
DB 10,2,8,1,8,1,8,2,6,2,10,1,9,1,9,2,9,4//你永远的幸福
DB 5,1,5,1,12,1,12,1,9,1,10,3,8,8,0xff;是我最大的心愿
//******猪八戒背媳妇********/
//注释的地方字数太多,导致计数器R2到最大值后,回到0,
//重复执行该代码 ,造成一首歌曲重复播放。可以删除该部分内容
TIME3:
// DB 6,4,10,3,12,1,10,2,6,2,8,4
// DB 6,1,8,1,6,1,8,1,10,2,10,2
// DB 10,1,9,1,10,1,8,1,6,4
// DB 10,3,12,1,13,2,13,2,13,2,10,2,12,4
// DB 10,1,12,1,10,1,12,1,13,2,13,2
// DB 13,2,10,2,12,4,12,2,6,2,12,2,6,2
// DB 10,2,10,2,8,4,9,4,9,4
// DB 9,2,8,1,9,1,10,2,12,2,13,4,17,4
// DB 10,4,17,4,10,2,17,2,10,2,10,2
// DB 10,2,17,2,9,1,10,1,9,1,10,1
DB 8,4,10,3,12,1,10,2,6,2,8,4
DB 6,1,8,1,6,1,8,1,10,2,10,2
DB 10,1,9,1,10,1,8,1,6,4
DB 10,2,10,1,12,1,13,2,13,2
DB 13,2,10,2,12,4,10,1,12,1,10,1,12,1,13,2,13,2
DB 13,2,10,2,12,4,12,2,6,2,12,2,6,2
DB 10,2,10,2,8,4,9,4,9,4,9,2,8,1,9,1,10,2,12,2
DB 13,4,17,4,10,4,17,4,10,2,17,2,10,2,17,2
DB 9,1,10,1,9,1,10,1,8,4,6,4,10,2,12,2
DB 10,2,6,2,8,4,6,1,8,1,6,1,8,1,10,4
DB 10,1,9,1,10,1,8,1,6,4,10,3,12,1,13,2,13,2
DB 13,2,10,2,12,4,10,1,12,1,10,1,12,1,13,2,13,2
DB 13,2,10,2,12,4,12,2,6,2,12,2,6,2,10,2,10,2,8,4
DB 9,4,9,4,9,2,8,1,9,1,10,2,12,2,13,8,0xff
END
技术有限,欢迎评论指正