ORG 0000H
MOV P2,#11111111B
MOV P3,#11111111B
TEST: JNB P2.0,DO1 ;P2.0=0
JNB P2.1, RE1;P2.1=0
JNB P2.2, MI1;P2.2=0
JNB P2.3,FA1;P2.3=0
JNB P2.4,SO1;P2.4=0
JNB P2.5,LA1;P2.5=0
JNB P2.6,SI1;P2.6=0
JNB P2.7,DOH1;P2.7=0
JNB P3.0, START;P3.0=0
AJMP TEST
DO1:MOV R6,#126
AJMP OUTPUT1
RE1:MOV R6, #113
AJMP OUTPUT1
MI1:MOV R6, #100
AJMP OUTPUT1
FA1:MOV R6,#95
AJMP OUTPUT1
SO1:MOV R6, #85
AJMP OUTPUT1
LA1:MOV R6,#75
AJMP OUTPUT1
SI1:MOV R6,#67
AJMP OUTPUT1
DOH1:MOV R6,#63
AJMP OUTPUT1
OUTPUT1: CLR P3.7;令扬声器通电
ACALL DELAY;延时半周期t
SETB P3.7;令扬声器断电
ACALL DELAY;延时半周期t
AJMP TEST ;重新测试按键
START: MOV DPTR, #MUSIC;DPTR指向乐谱的开头
CONT: CLR A ;读取乐谱内代码的音阶
MOVC A,@A+DPTR ;A=音阶代码
CJNE A,#40,CHK ;若音阶代码为40
AJMP START ;则从头开始演奏
CHK:PUSH ACC ;保存A的内容
INC DPTR
CLR A ;读取乐谱内的音拍代码
MOVC A, @A+DPTR;
MOV R4,A ;R4=音拍代码取回A的内容
POP ACC
CHK1: CJNE A, #01, CHK2 ; 若音阶代码为01,
ACALL DO ;则产生中音DO的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK2: CJNE A, #02, CHK3 ;若音阶代码为02
ACALL RE ;产生中音RE的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK3: CJNE A, #03, CHK4 ;若音阶代码为03
ACALL MI ;则产生中音MI的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK4: CJNE A, #04, CHK5 ;若音阶代码为04
ACALL FA ;则产生中音FA的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK5: CJNE A, #05, CHK6 ;若音阶代码为05
ACALL SO ;则产生中音SO的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK6: CJNE A, #06, CHK7 ;若音阶代码为06
ACALL LA ;则产生中音LA的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK7: CJNE A, #07, CHK8 ;若音阶代码为07,
ACALL SI ;则产生中音SI的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK8: CJNE A, #08, CHK0 ;若音阶代码为08
ACALL DOH ;则产生高音D0的声音
JNB P3.2, STOP ;若P3.2=0,则停止演奏
CHK0: CJNE A, #00, CONT2 ;若音阶代码为00
ACALL NON ;则不发出声音
CONT2:
INC DPTR ;继续读取乐谱
AJMP CONT
DO: MOV R6,#126 ;设R6=延时参数,R5=音长参数
MOV R5,#33 ;设定中音DO的相应参数
AJMP OUTPUT
RE: MOV R6,#113 ;设定中音RE的相应参数
MOV R5,#37
AJMP OUTPUT
MI: MOV R6,#100 ;设定中音M的相应参数
MOV R5,#41
AJMP OUTPUT
FA: MOV R6,#95 ;设定中音FA的相应参数
MOV R5,#44
AJMP OUTPUT
SO: MOV R6, #85 ;设定中音S0的相应参数
MOV R5,#49
AJMP OUTPUT
LA: MOV R6,#75 ;设定中音LA的相应参数
MOV R5,#55
AJMP OUTPUT
SI: MOV R6,#67 ;设定中音SI的相应参数
MOV R5,#62
AJMP OUTPUT
DOH:MOV R6,#63 ;设定高音DO的相应参数
MOV R5,#65
AJMP OUTPUT
NON:MOV R6,#33 ;设定休止符的相应参数
MOV R5,#00
AJMP OUTPUT
OUTPUT:MOV ACC,R5
LOOP:CJNE A,#00,SOUND ;若音阶代码为00,则不让扬声器通电
LJMP MUTE
SOUND: CLR P3.7 ;令扬声器通电
MUTE: ACALL DELAY ;延时半周期
SETB P3.7 ;令扬声器断电
ACALL DELAY ;延时半周期
DJNZ R5, LOOP ;输出一个音长,共R5周的方波
MOV R5, ACC ;取回R5的内容
DJNZ R4, OUTPUT ;共输出R4个音长
REST: MOV R6, #170 ;静音
MOV R5, #20
WAIT: ACALL DELAY
DJNZ R5,WAIT
DELAY: MOV B,R6 ;延时半周期t=15μs×R6+9us
DL: MOV R7, #6
DJNZ R7,$
DJNZ R6,DL
MOV R6,B
RET
MUSIC: DB 03,02,03,02,03,04
DB 01,04
DB 03,02,03,02,03,04
DB 01,04
DB 05,02,06,02,05,02
DB 04,02,03,02,04,02
DB 05,08
DB 04,02,04,02,04,04
DB 02,04
DB 04,02,04,02,04,04
DB 02,04
DB 05,02,06,02,05,02
DB 04,02,03,02,02,02
DB 01,08
DB 06,04,05,08
DB 06,04,05,08
DB 05,02,06,02,05,02
DB 04,02,03,02,02,02
DB 01,08
DB 40
END
|