ORG 0000H ;主程序起始地址
LJMP KONGZHI ;跳至控制程序
ORG 000BH ;TIMER0中斷起始地址
LJMP TIM0 ;跳至TIMER0中斷子程
KONGZHI: MOV P1,#0FFH ;P1口初始化(低四位為輸入、高四位輸出口)
JNB P1.0,MUSIC1 ;P1.0口為0放第一曲
JNB P1.1,MUSIC2 ;P1.1口為0放第二曲
JNB P1.2,MUSIC3 ;P1.2口為0放第三曲
JNB P1.3,XUNHUAN ;P1.3口為0執(zhí)行循環(huán)
MOV 5CH,#00H ;P1.3口為1順序執(zhí)行一次結(jié)束
AJMP START ;放第一首歌曲
MUSIC1: MOV 5CH,#00H ;取第一首歌的簡譜指針
MOV 20H,P1 ;將P1.0口的值暫存于20H單元
SETB P1.0 ;恢復P1.0的初值
AJMP START ;執(zhí)行循環(huán)
MUSIC2: MOV 5CH,#01H ;取第二首歌的簡譜指針
MOV 20H,P1 ;將P1.1口的值暫存于20H單元
SETB P1.1 ;恢復P1.1的初值
AJMP START ;執(zhí)行循環(huán)
MUSIC3: MOV 5CH,#02H ;取第三首歌的簡譜指針
MOV 20H,P1 ;將P1.2口的值暫存于20H單元
SETB P1.2 ;恢復P1.2的初值
AJMP START ;執(zhí)行循環(huán)
XUNHUAN: MOV 5CH,#00H
MOV 21H,P1 ;將P1.3口的值暫存于21H單元
SETB P1.3 ;恢復P1.3的初值
AJMP START ;跳至主程序
START: MOV TMOD,#01H ;設TIMER0在MODE1
MOV IE,#82H ;中斷使能
START0: MOV 30H,#00H ;取簡譜碼指針
NEXT: MOV A,30H ;簡譜碼指針載入A
MOV DPTR,#TABLE ;至TABLE取簡譜碼
MOVC A,@A+DPTR
MOV R2,A ;取到的簡譜碼暫存于R2
JZ END0 ;是否取到00(結(jié)束碼)?
ANL A,#0FH ;不是,則取低4位(節(jié)拍碼)
MOV 90H,A ;為調(diào)速保存數(shù)據(jù)
MOV R5,A ;將節(jié)拍碼存入R5
MOV A,R2 ;將取到的簡譜碼再載入A
SWAP A ;高低4位交換
ANL A,#0FH ;取低4位(音符碼)
MOV 90H,A ;保存音符碼,為調(diào)速做準備
JNZ SING ;取到的音符碼是否為0?
CLR TR0 ;是,則不發(fā)音
JMP D1 ;跳至D1
SING: DEC A ;取到的音符碼減1(不含0)
MOV 22H,A ;存入(22H)
RL A ;乘2
MOV DPTR,#TABLE1 ;至TABLE1取相對的高位字節(jié)計數(shù)值
MOVC A,@A+DPTR
MOV TH0,A ;取到的高位字節(jié)存入TH0
MOV 21H,A ;取到的高位字節(jié)存入(21H)
MOV A,22H ;再載入取到的音符碼
RL A ;乘2
INC A ;加1
MOVC A,@A+DPTR ;至TABLE1取相對的低位字節(jié)計數(shù)值
MOV TL0,A ;取到的低位字節(jié)存入TL0
MOV 20H,A ;取到的低位字節(jié)存入(20H)
SETB TR0 ;啟動TIMER0
D1: LCALL TIAOSU ;調(diào)用以1/4拍為基本單位時間的調(diào)速子程序
INC 30H ;取簡譜碼指針加1
JMP NEXT ;取下一個碼
END0: CLR TR0 ;停止TIMER0
JMP START0 ;重復循環(huán)
TIM0: PUSH ACC ;將A的值暫存于堆棧
PUSH PSW ;將PSW的值暫存于堆棧
MOV TL0,20H ;重設計數(shù)值
MOV TH0,21H
CPL P1.0 ;將P1.0位反相
POP PSW ;至堆棧取回PSW的值
POP ACC ;至堆棧取回A的值
RETI ;返回主程序
TABLE1:
DW 63625,63833,64019,64104,64260,64400,64524 ;低音區(qū):1 2 3 4 5 6 7
DW 64580,64685,64778,64820,64898,64968,65030 ;中音區(qū):1 2 3 4 5 6 7
DW 65058,65110,65157,65178,65217,65252,65283 ;高音區(qū):1 2 3 4 5 6 7
DW 65297 ;超高音:1
|