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执行循环
MOV 5CH,#00H ;P1.3口为1顺序执行一次结束
AJMP START ;放第一首歌曲
MUSIC1: MOV 5CH,#00H ;取第一首歌的简谱指针
MOV 20H,P1 ;将P1.0口的值暂存于20H单元
SETB P1.0 ;恢复P1.0的初值
AJMP START ;执行循环
MUSIC2: MOV 5CH,#01H ;取第二首歌的简谱指针
MOV 20H,P1 ;将P1.1口的值暂存于20H单元
SETB P1.1 ;恢复P1.1的初值
AJMP START ;执行循环
MUSIC3: MOV 5CH,#02H ;取第三首歌的简谱指针
MOV 20H,P1 ;将P1.2口的值暂存于20H单元
SETB P1.2 ;恢复P1.2的初值
AJMP START ;执行循环
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(结束码)?
ANL A,#0FH ;不是,则取低4位(节拍码)
MOV 90H,A ;为调速保存数据
MOV R5,A ;将节拍码存入R5
MOV A,R2 ;将取到的简谱码再载入A
SWAP A ;高低4位交换
ANL A,#0FH ;取低4位(音符码)
MOV 90H,A ;保存音符码,为调速做准备
JNZ SING ;取到的音符码是否为0?
CLR TR0 ;是,则不发音
JMP D1 ;跳至D1
SING: DEC A ;取到的音符码减1(不含0)
MOV 22H,A ;存入(22H)
RL A ;乘2
MOV DPTR,#TABLE1 ;至TABLE1取相对的高位字节计数值
MOVC A,@A+DPTR
MOV TH0,A ;取到的高位字节存入TH0
MOV 21H,A ;取到的高位字节存入(21H)
MOV A,22H ;再载入取到的音符码
RL A ;乘2
INC A ;加1
MOVC A,@A+DPTR ;至TABLE1取相对的低位字节计数值
MOV TL0,A ;取到的低位字节存入TL0
MOV 20H,A ;取到的低位字节存入(20H)
SETB TR0 ;启动TIMER0
D1: LCALL TIAOSU ;调用以1/4拍为基本单位时间的调速子程序
INC 30H ;取简谱码指针加1
JMP NEXT ;取下一个码
END0: CLR TR0 ;停止TIMER0
JMP START0 ;重复循环
TIM0: PUSH ACC ;将A的值暂存于堆栈
PUSH PSW ;将PSW的值暂存于堆栈
MOV TL0,20H ;重设计数值
MOV TH0,21H
CPL P1.0 ;将P1.0位反相
POP PSW ;至堆栈取回PSW的值
POP ACC ;至堆栈取回A的值
RETI ;返回主程序
TABLE1:
DW 63625,63833,64019,64104,64260,64400,64524 ;低音区:1 2 3 4 5 6 7
DW 64580,64685,64778,64820,64898,64968,65030 ;中音区:1 2 3 4 5 6 7
DW 65058,65110,65157,65178,65217,65252,65283 ;高音区:1 2 3 4 5 6 7
DW 65297 ;超高音:1
|