单片机音乐程序
利用单片机(或单板机)奏乐大概是无线电爱好者感兴趣的问题之一。本文从单片机的基本发间实验出发,谈谈音乐程序的设计原理,并给出具体实例,以供参考。下面提供2个列子,大家根据 需要自行选择
单片机最小系统,两位LED数码管由串口输出接两个164驱动,Lout,Rout为左右声道输出,SET, ALT0, ALT1为三个按键,也可自己在开始的I/O定义改成你想用的I/O口;12M晶振若用89C51则只可装下约14首歌曲,用89C52则可装下近40曲
源程序; Electronic Music; Version 4.50; Copyright (c) XAJ
2001;============================LOUT BIT P1.0 ;左声道输出ROUT BIT P1.2 ;右声道输出SET BIT P3.3 ;SET按键ALT0 BIT P3.6 ;ALT0按键ALT1 BIT P3.7 ;ALT1按键
;REPNUM EQU 09H重复段编号STATU EQU 0AH;状态寄存器LDYDSR EQU 0BH;左低音度数RDYDSR EQU 0CH;右低音度数LDYAR EQU 0DH;左低音协助RDYAR EQU 0EH;右低音协助JPCLK EQU 0FH;节拍时钟GENCLK EQU 10H;通用时钟SNSDCLK EQU 11H;搜、存显示时钟GEN16T0 EQU 12H;通用16位时钟GEN16T1 EQU 13H; SETST0 EQU 14H;设置状态SETST1 EQU 15H; 定时时钟DISNUM0 EQU 16H;显示数值DISNUM1 EQU 17H;寄存器(2位)CSN EQU 18H;当前曲曲号REP0L EQU 19H;0号重复段地址REP0H EQU 1AH;REP1L EQU 1BH;1号重复段地址REP1H EQU 1CH;REP2L EQU 1DH;2号重复段地址REP2H EQU 1EHREP3L EQU 1FH;3号重复段地址REP3H EQU 23H;COSPEEDN EQU 24H;SPENR EQU 25H;
LOCF BIT 00H;左声道开关标志ROCF BIT 01H;右声道开关标志SECHSTOF BIT 02H;搜索、存储标志NEXTSF BIT 03H;下一曲标志CSBESTOF BIT 04H;当前曲锁存/释放CUYFD BIT 05H;当前音符显示KSETF BIT 06H;SET键按下标志KALT0F BIT 07H;ALT0键按下标志KALT1F BIT 08H;ALT1键按下标志SPEEDF BIT 09H;速度增/减标志TONEF BIT 0AH;音调增/减标志YPBIT BIT 0BH;音频逻辑输出KBDISF BIT 0CH;键盘显示标志REP0F BIT 0DH;0号重复段控制REP1F BIT 0EH;1号重复段控制REP2F BIT 0FH;2号重复段控制REP3F BIT 10H;3号重复段控制
SBOTM EQU 25H;堆栈区(栈底)BUFF0 EQU 43H;锁存曲数BUFF EQU 44H;锁存曲缓冲区;============================
;=========BEGIN==============ORG MAIN;---------T0INT--------------ORG 000BHLJMP T0INT
0000HLJMP
;---------T1INT--------------ORG 001BHLJMP T1INT;1.音频发生
器;---------YPFSQ(01)----------ORG 0030HT0INT: MOV TL0,R4MOV TH0,R5PUSH PSWPUSH ACCPUSH 01HJB LOCF,ROPERMOV R1,#00HMOV A,LDYART0LLOP: RRC AMOV YPBIT,CXCH A,R1CJNE A,LDYDSR,T0LNEXTMOV C,YPBITMOV LOUT,CINC LDYAR; INC P0 SJMP ROPERT0LNEXT: XCH A,R1INC R1SJMP T0LLOPROPER: JB ROCF,T0RETIMOV R1,#00HMOV A,RDYART0RLOP: RRC AMOV YPBIT,CXCH A,R1CJNE A,RDYDSR,T0RNEXTMOV C,YPBITMOV ROUT,CINC RDYAR; INC P2SJMP T0RETIT0RNEXT: XCH A,R1INC R1SJMP T0RLOPT0RETI: POP 01HPOP ACCPOP PSWRETI;2.通用时钟;---------CLOCK(02)----------T1INT: MOV TL1,#0F0HMOV TH1,#0D8HPUSH PSWPUSH ACCINC JPCLKINC GENCLKINC SNSDCLKMOV A,SNSDCLKCJNE A,#0FFH,T1NEXTCLR SECHSTOFT1NEXT: INC GEN16T0MOV
A,GEN16T0CJNE A,#100,T1NEXT0MOV GEN16T0,#00HINC GEN16T1T1NEXT0: INC SETST0MOV A,SETST0CJNE A,#100,T1RETIMOV SETST0,#00HINC SETST1MOV A,SETST1CJNE A,#20,T1RETIMOV SETST1,#00HMOV STATU,#00HT1RETI: POP ACCPOP PSWRETI;3.显示子程序;---------DISPLAY(03)--------DISPLAY: PUSH ACCPUSH DPLPUSH DPHMOV DPTR,#T_FIGCODEMOV A,DISNUM0MOVC A,@A DPTRMOV SBUF,AJNB TI,$CLR TIMOV A,DISNUM1MOVC A,@A DPTRMOV SBUF,AJNB
TI,$CLR
TIPOP
DPHPOP
DPLPOP
ACCRETT_FIGCODE:DB
088H,0EBH,04CH,049H; 0 1 2 3DB 02BH,019H,018H,0CBH; 4 5 6 7DB 008H,009H,00AH,038H; 8 9 A BDB 09CH,068H,01CH,01EH; C D E FDB 080H,0E3H,044H,041H; 0. 1. 2. 3.DB 023H,011H,010H,0C3H; 4. 5. 6. 7.DB 000H,001H,002H,030H; 8. 9. A. B.DB 094H,060H,014H,016H; C. D. E. F.DB 0FFH,02FH,098H,07FH; 熄灭 # G -DB 07CH,078H,0BCH,00AH; c o L RDB 029H; Y;4.主程序MAIN;---------MAIN(04)-----------MAIN: MOV R0,#01HCLR ACLRAM: MOV @R0,AINC R0CJNE R0,#80H,CLRAMMOV R0,AMOV SP,#SBOTMMOV 08H,#BUFF;MOV
09H,#BUFFMOV
SCON,#00HMOV
TMOD,#11HMOV
TL1,#0F0HMOV TH1,#0D8HSETB EASETB ET0SETB ET1SETB TR1
START: MOV DPTR,#T_SONGSRYF: LCALL RYFSUPMOV A,R7JZ STARTCJNE R7,#0FFH,SYFJBC NEXTSF,NEXTSCLMOV A,STATUJNZ GONSBQMOV A,BUFF0JNZ MPSQCLLCALL PAQSCLSJMP MQNFDMPSQCL: LCALL PSQSCLMQNFD: LCALL QNFDSUPMOVPJRYF: INC DPTRINC DPTRSJMP RYFNEXTSCL: LCALL CSBESTOJGJB CSBESTOF,CALLPSCLLCALL
PAQSCLSJMP
MOVPJRYFCALLPSCL:
LCALL
PSQSCLSJMP MOVPJRYFGONSBQ: LCALL CSDPTRINC DPTRINC DPTRSJMP MOVPJRYFSYF:
CJNE
R6,#0FFH,CALLPLAYLCALL
REPCLSUPSJMP
MOVPJRYFCALLPLAY: LCALL YFDSUPLCALL PLAYSJMP MOVPJRYF;5.读音符子程
序;---------RYFSUP(05)--------RYFSUP: CLR AMOVC A,@A DPTRMOV R6,AMOV A,#01HMOVC
A,@A
DPTRMOV
R7,ARET
;
6.
统
唱
曲
首
处
理;---------PAQSCL(06)--------PAQSCL: MOV CSN,R6INC DPTRINC DPTRLCALL RYFSUPMOV
02H,R6MOV
03H,R7RET;7.
存
唱
曲
首
处
理;---------PSQSCL(07)--------PSQSCL: PUSH PSWSETB RS0CLR RS1PSQC7E: CJNE R0,#7EH,PSQNEXTPSQNEXT:
JC
PSQNEXT1MOV
R0,#BUFFSJMP
PSQC7EPSQNEXT1: MOV A,@R0JNZ PSQNEXT2INC R0INC R0INC R0SJMP PSQC7EPSQNEXT2:
MOV
CSN,@R0INC
R0MOV
02H,@R0INC
R0MOV
03H,@R0INC R0POP PSWLCALL CSDPTRINC DPTRINC DPTRRET;8.曲号闪显子程序;---------QNFDSUP(08)-------QNFDSUP: PUSH ACCMOV GEN16T0,#00HMOV GEN16T1,#00HQNGON: GENCLK,#00HQNWAIT: DISNUM0,#20HMOV GENCLK,#00HQNWAIT1:
LCALL MOV
CSNSDISNLCALL A,GENCLKCJNE
DISPLAYMOV
A,#35,QNWAITMOV
DISPLAYMOV
A,#15,QNWAIT1MOV
DISNUM1,#20HLCALL MOV
A,GENCLKCJNE
A,GEN16T1CJNE A,#02,QNGONPOP ACCRET;9.曲号送显示寄存器;---------CSNSDISN(09)------CSNSDISN:
MOV
A,CSNANL
A,#0FHLCALL
CSBESTOJGJNB CSBESTOF,NADPADD A,#10HNADP: MOV DISNUM0,AMOV A,CSNSWAP AANL A,#0FHMOV DISNUM1,ARET;10.当前曲是否被存储判断;---------CSBESTOJG(10)-----CSBESTOJG:PUSH ACCPUSH PSWMOV A,BUFF0JZ CLRCSTOFMOV R0,#BUFFCSBCMPCSN:MOV A,@R0CJNE A,CSN,CSBGSCANSETB CSBESTOFSJMP
CSBRETCSBGSCAN:
INC
R0INC
R0INC
R0CJNE
R0,#7EH,CSBNEXTCSBNEXT: JC CSBCMPCSNCLRCSTOF: CLR CSBESTOFMOV R0,#BUFFCSBCMP0: MOV A,@R0JZ CSBRETINC R0INC R0INC R0CJNE R0,#7EH,CSBNEXT1CSBNEXT1: JC CSBCMP0CSBRET: POP PSWPOP ACCRET;11.找当前曲首址;---------CSDPTR(11)--------CSDPTR: MOV DPTR,#T_SONGSCSDSCAN:
LCALL RYFSUPCJNE R7,#0FFH,CSDNEXTMOV A,R6CJNE A,CSN,CSDNEXTSJMP CSDRETCSDNEXT: INC DPTRINC DPTRSJMP CSDSCANCSDRET: RET;12.重复段处理子程序;---------REPCLSUP(12)------REPCLSUP: MOV A,R7ANL A,#0FHCJNE A,#02H,CMPA3MOV
A,R7SWAP
AANL
A,#0FHJNZ
H4CMP1JNB
REP0F,REPRET0CLR REP0FMOV DPL,REP0LMOV DPH,REP0HREPRET0: RETH4CMP1: CJNE
A,#01H,H4CMP2JNB
REP1F,REPRETCLR
REP1FMOV
DPL,REP1LMOV
DPH,REP1HRETH4CMP2: CJNE A,#02H,H4CMP3JNB REP2F,REPRETCLR REP2FMOV DPL,REP2LMOV
DPH,REP2HRETH4CMP3:
CJNE
A,#03H,REPRETJNB
REP3F,REPRETCLR REP3FMOV DPL,REP3LMOV DPH,REP3HRETCMPA3: CJNE A,#03H,REPRETMOV A,R7SWAP AANL A,#0FHJNZ H4VS1SETB REP0FMOV REP0L,DPLMOV REP0H,DPHSJMP SREPHADH4VS1: CJNE A,#01H,H4VS2SETB REP1FMOV
REP1L,DPLMOV
REP1H,DPHSJMP
SREPHADH4VS2:
CJNE
A,#02H,H4VS3SETB SREPHADH4VS3:
REP2FMOV REP2L,DPLMOV
REP3FMOV
REP2H,DPHSJMP REP3L,DPLMOV
CJNE A,#03H,REPRETSETB
REP3H,DPHSREPHAD: MOV 09H,ALCALL CSDPTRREPGON: INC DPTRINC DPTRLCALL RYFSUPCJNE R6,#0FFH,REPGONMOV A,R7SWAP AANL A,#0FHCJNE A,09H,REPGONREPRET: 序
RET
;
13.
音MOV
符
显
示
子
程
;---------YFDSUP(13)--------YFDSUP: A,STATUJNZ MOV
YFDRETJB
SECHSTOF,YFDRETJNB CUYFD,YFSLEDXZFCLD: DISNUM0,#20HMOV
DISNUM1,#20HSJMP YFDSPLAYYFSLED: MOV A,R6JZ XZFCLDANL A,#0FHPUSH DPLPUSH DPHMOV DPTR,#T_YFDCODMOVC A,@A DPTRMOV DISNUM0,APOP DPHPOP DPLMOV A,R6SWAP AANL A,#0FHMOV DISNUM1,AYFDSPLAY: LCALL DISPLAYYFDRET: RETT_YFDCOD: DB 20H ;--DB 01H ; 1DB 02H ; 2DB 03H ; 3 DB 04H ; 4DB 05H ; 5DB 06H ; 6DB 07H ; 7DB 11H ;#1DB 12H ;#2DB 14H ;#4DB 15H ;#5DB 16H ;#6;14.唱音符子程序;---------PLAY(14)----------PLAY: MOV A,R6JZ
PCOSPECLPUSH DPLPUSH DPHMOV DPTR,#T_SDANL A,#0FHMOVC A,@A DPTRXCH A,R6SWAP AANL A,#0FHMOV B,#12MUL ABADD A,R6ADD A,R2RL AMOV R6,AMOV DPTR,#T_RANMOVC A,@A DPTRMOV TH0,AMOV R5,AMOV A,R6INC AMOVC A,@A DPTRMOV TL0,AMOV R4,APOP DPHPOP DPLSETB TR0PCOSPECL: LCALL COSPECLPJPWAIT: MOV JPCLK,#00HPDELAY: LCALL KCXCLJB NEXTSF,PRETMOV A,JPCLKCJNE A,01H,PNEXTPNEXT: JC PDELAYDJNZ R7,PJPWAITPRET: CLR TR0RET;---------TABSD-------------T_SD: DB 01h ;uselessDB 01HDB 03HDB 05HDB 06HDB 08H DB 0AHDB 0CHDB 02H DB 04H DB 07H DB 09H DB 0bH;---------TABRAN------------T_RAN: DW 0F111H ;uselessdw 0f111h ; area 0dw 0f1e8h dw 0f2b2h dw 0f373h dw 0f426h dw 0f4eeh dw 0f571h dw 0f609h dw 0f699h dw 0f71fh dw 0f79fh dw 0f817h dw 0f889h ; area 1dw 0f8f4h dw 0f95ah dw 0f9b9h dw 0fa13h dw 0fa68h dw 0fab9h dw 0fb04h dw 0fb4ch dw 0fb90h dw 0fbcfh dw 0fc0ch dw 0fc45h ;area 2dw 0fc7ah dw 0fcadh dw 0fcdch dw 0fd0ah dw 0fd34h dw 0fd5ch dw 0fd82h dw 0fda6h dw 0fdc8h dw 0fde8h dw 0fe06h dw 0fe22h ; area 3dw 0fe3dh dw 0fe56h dw 0fe6eh dw 0fe85h dw 0fe9ah dw 0feaeh dw 0fec1h dw 0fed3h dw 0fee3h dw 0fef4h dw 0ff02h dw 0ff11h ;area 4dw 0ff1fh dw 0ff2bh dw 0ff37h dw 0ff42h dw 0ff4dh dw 0ff57h dw 0ff60h dw 0ff6ah dw 0ff72h
dw
0ff7ah
dw
0ff81h
dw
0ff89h
;
5;15.共速处
理;---------COSPECL(15)-------COSPECL: MOV R1,03HMOV A,COSPEEDNJZ COSPRETPUSH COSPEEDNMOV A,R1COSPEGON: MOV B,#08HMUL ABCLR CSUBB A,R1JNC COSPNEXTDEC BCOSPNEXT: MOV R6,#03HDIV8: CLR CXCH A,BRRC AXCH A,BRRC ADJNZ R6,DIV8MOV R1,ADJNZ COSPEEDN,COSPEGONPOP COSPEEDNMOV A,R1JNZ COSPRETMOV R1,#01HCOSPRET: RET;16.键盘查询处理;---------KCXCL(16)---------KCXCL: LCALL KSETLCALL KALT0LCALL KALT1JNB KSETF,KNEXT0LCALL KSETCLKSETSTC: MOV SETST0,#00HMOV SETST1,#00HSETB
KBDISFSJMP KDISKNEXT0: JNB KALT0F,KNEXT1LCALL KALT0CLSJMP
KSETSTCKNEXT1: JNB KALT1F,KDISLCALL KALT1CLSJMP KSETSTCKDIS: MOV A,STATUJNZ KBDISFLCALL 询
KSSNSDJNB
SECHSTOF,KRETKSSNSD:
RET
;
17.KSETSETB
JNB 键SETJB
是
KBDISF,KRETCLR 否
按
下
查
DISPLAYKRET:
;---------KSET(17)----------KSET:
MOV
SET,CSETRETMOV
SETJB
GENCLK,#00HSETLOP: SET,CSETRETCLR
A,GENCLKCJNE
SETB
A,#02,SETLOPSETB SETJNB
TR0SETWAIT: SET,SETWAITMOV
GENCLK,#00HSETLOP1: MOV A,GENCLKCJNE A,#02,SETLOP1SETB TR0SETB KSETFRETCSETRET: 询
CLR
KSETFRET
;
18.KALT0
键
是
否
按
下
查
;---------KALT0(18)---------KALT0:
MOV
SETB ALT0JB ALT0,CALT0RETMOV
ALT0JB
GENCLK,#00HALT0LOP: ALT0,CALT0RETCLR
A,GENCLKCJNE
SETB
A,#02,ALT0LOPSETB
TR0ALT0WAIT: ALT0JNB ALT0,ALT0WAITMOV
GENCLK,#00HALT0LOP1: MOV A,GENCLKCJNE A,#02,ALT0LOP1SETB TR0SETB KALT0FRETCALT0RET: 询
CLR
KALT0FRET;19.KALT1
SETB
ALT1JB
键是否按下查ALT1,CALT1RETMOV
ALT1JB
;---------KALT1(19)---------KALT1:
MOV
GENCLK,#00HALT1LOP: ALT1,CALT1RETCLR
A,GENCLKCJNE
SETB
A,#02,ALT1LOPSETB
TR0ALT1WAIT: ALT1JNB ALT1,ALT1WAITMOV
GENCLK,#00HALT1LOP1: MOV A,GENCLKCJNE A,#02,ALT1LOP1SETB TR0SETB KALT1FRETCALT1RET: 理
CLR
KALT1FRET;20.SETINC
STATUMOV MOV
键
处
;---------KSETCL(20)--------KSETCL: A,STATUCJNE
A,#07H,STATUDISMOV STATU,#00HSTATUDIS: DISNUM0,#23HMOV
DISNUM1,STATURET;21.KALT0键处理;---------KALT0CL(21)-------KALT0CL: MOV A,STATUJNZ CASEB1KA0S0GO: INC DPTRINC DPTRLCALL RYFSUPMOV A,R7JNZ EQUFFMOV DPTR,#T_SONGSSJMP KA0NEXTEQUFF: INC AJNZ KA0S0GOKA0NEXT: LCALL RYFSUPMOV CSN,R6LCALL CSNSDISNMOV A,DPLCLR CSUBB A,#02HJNC
KA0NEXT1DEC DPHKA0NEXT1: MOV DPL,ACLR REP0FCLR REP1FCLR REP2FCLR REP3FSETB
NEXTSFSETB
SECHSTOFRETCASEB1:
CJNE
A,#01H,CASEB2INC
LDYDSRMOV A,LDYDSRCJNE A,#04H,LDYDSL4MOV LDYDSR,#00HLDYDSL4: MOV DISNUM0,LDYDSRMOV DISNUM1,#26HRET
HCOSPEEDN EQU 12HCASEB2: CJNE A,#02H,CASEB3MOV A,COSPEEDNCJNE A,#HCOSPEEDN,KA0NEXT4KA0NEXT4: JNC KA0NEXT5INC COSPEEDNKA0NEXT5: MOV SPENR,COSPEEDNLCALL SPENSDISNRETCASEB3: CJNE A,#03H,CASEB4CLR SPEEDFLCALL SPEEDCLRETCASEB4: CJNE A,#04H,CASEB5CLR TONEFLCALL TONECLRETCASEB5: CJNE A,#05H,CASEB6CPL LOCFJNB LOCF,KA0NEXT2MOV DISNUM0,#24HSJMP KA0NEXT3KA0NEXT2: MOV DISNUM0,#25HKA0NEXT3: MOV
DISNUM1,#26HRETCASEB6:
CJNE
A,#06H,KA0RETCPL
CUYFDJNB
MOV
CUYFD,KA0NEXT6MOV DISNUM0,#24HSJMP KA0NEXT7KA0NEXT6:
DISNUM0,#25HKA0NEXT7: MOV DISNUM1,#28HKA0RET: RET;22.速度数送显示寄存器;---------SPENSDISN(22)----SPENSDISN:MOV A,SPENRANL A,#0FHMOV DISNUM0,AMOV A,SPENRSWAP AANL A,#0FHMOV DISNUM1,ARET;23.速度处理;---------SPEEDCL(23)------HSPEED EQU 02H; LSPEED EQU 50H; SPEEDCL: JB SPEEDF,DNSPEEDCJNE R3,#HSPEED,SCLNEXTSCLNEXT: JC SCLNEXT1DEC R3SJMP SCLNEXT1DNSPEED: CJNE R3,#LSPEED,SCLNEXT2SCLNEXT2: JNC SCLNEXT1INC R3SCLNEXT1: LCALL CSBESTOJGJNB CSBESTOF,SCLNEXT3INC R0INC R0MOV @R0,03HSCLNEXT3: LCALL COSPECLMOV SPENR,R1LCALL SPENSDISNRET;24.音调处理;---------TONECL(24)---------;LTONE EQU 00 ;CHTONE EQU 11 ;BTONECL: JB TONEF,DNTONECJNE R2,#HTONE,TCLNEXT0TCLNEXT0: JNC TCLNEXTINC R2SJMP TCLNEXTDNTONE: MOV A,R2JZ TCLNEXTDEC R2TCLNEXT: LCALL CSBESTOJGJNB CSBESTOF,TCLNEXT1INC R0MOV @R0,02HTCLNEXT1: PUSH DPLPUSH DPHMOV
DPTR,#T_TONDISCMOV A,R2RL AMOVC A,@A DPTRMOV DISNUM1,AMOV A,R2RL
AINC
AMOVC
A,@A
DPTRMOV
DISNUM0,APOP
DPHPOP
DPLRETT_TONDISC:DW 200CH ; CDW 210CH ;#CDW 200DH ; DDW 210DH ;#DDW 200EH ; EDW 200FH ; FDW 210FH ;#FDW 2022H ; GDW 2122H ;#GDW 200AH ; ADW 理
210AH
;#ADW
200BH
; MOV
B;25.KALT1A,STATUJNZ
键
处
;---------KALT1CL(25)--------KALT1CL: CASE1LCALL BUFF0SJMP
CSBESTOJGJNB CSBESTOF,KA1NEXTMOV @R0,#00HDEC
KA1NEXT2KA1NEXT: CJNE R0,#7EH,KA1NEXT1KA1NEXT1: JNC KA1NEXT2MOV @R0,CSNINC R0MOV @R0,02HINC R0MOV @R0,03HINC BUFF0KA1NEXT2: LCALL CSNSDISNSETB SECHSTOFRETCASE1: CJNE A,#01H,CASE2INC RDYDSRMOV A,RDYDSRCJNE
A,#04H,RDYDSL4MOV
RDYDSR,#00HRDYDSL4:
MOV
DISNUM0,RDYDSRMOV DISNUM1,#27HRETCASE2: CJNE A,#02H,CASE3MOV A,COSPEEDNJZ
KA1NEXT5DEC
COSPEEDNKA1NEXT5:
CJNE
MOV
SPENR,COSPEEDNLCALL SPEEDFLCALL
SPENSDISNRETCASE3:
CJNE
A,#03H,CASE4SETB
TONEFLCALL
SPEEDCLRETCASE4: A,#04H,CASE5SETB
TONECLRETCASE5: CJNE A,#05H,CASE6CPL ROCFJNB ROCF,KA1NEXT3MOV DISNUM0,#24HSJMP KA1NEXT4KA1NEXT3: MOV DISNUM0,#25HKA1NEXT4: MOV DISNUM1,#27HRETCASE6: CJNE A,#06H,KA1RETMOV DISNUM0,#23HMOV DISNUM1,#06HKA1RET:
RET;=========
乐
曲
表dw
============;---------SONGS--------------T_SONGS: 乐曲表表首
01ffh,;song1:xiao la ba...dw 0b05h,dw 2504h,dw 2604h,dw 2506h,dw 0002h,dw 2504h,dw 2604h,dw 2506h,dw 0002h,dw 2504h,dw 2604h,dw 2504h,dw 2304h,dw 2204h,dw 2104h,dw 2206h,
DW 16FFH;SONG16:Liang Zhi Lao HuDW 0715HDW 0FF21H ;REP21DW
0FF01H ;REP01DW 2102HDW 2202HDW 2302HDW 2102HDW 0FF02H ;REP02DW 0FF03H ;REP03DW 2302HDW 2402HDW 2504HDW 2302HDW 2402HDW 2504HDW 0FF11H ;REP11DW 2501HDW 2601HDW 2501HDW 2401HDW 2302HDW 2102HDW 0FF12H ;REP12DW 0FF13H ;REP13DW 2202HDW 1502HDW 2104HDW 2202HDW 1502HDW 2104HDW 0FF22H ;REP22DW 0FF23H ;REP23
DW 0000H ;乐曲表表尾END;=========END================注:设计者手头有近40首曲子的音乐数据(花了大量时间对简谱进行手工转换!),而每块AT89C51的4KROM种除指令外剩下空间只可放14首左右。这里给出第一曲和第16曲《两只老虎》作一示例。
1.
单片机的基本发音实验
我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单处机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的矩形波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。
例如,要产生200HZ的音频信号,按图1接入喇叭(若属临时实验,也可将喇叭直接接在P1口线上),实验程序为:
其中子程序DEL为延时子程序,当R3为1时,延时时间约为20us,R3中存放延时常数,对200HZ音频,其周期为1/200秒,即5ms。这样,当P1.4的高电平或低电平
的持续时间为2.5ms,即R3的时间常数取2500/20=125(7DH)时,就能发出200HZ的音调。将上述程序键入学习机,并不断修改R3的常数可以感到音调的变化。
乐曲中,每一音符对应着确定的频率,表1给出C调时各音符频率及其相应的时间常数。
读者可以根据表1所提供的常数,将其16进制代码送入R3,反复练习体会。根据表1可以奏出音符。仅这还不够,要准确奏出一首曲子,必须准确地控制乐曲节奏,即一音符的持续时间。
音符的节拍我们可以用定时器T0来控制,送入不同的初值,就可以产生不同的定时时间。便如某歌曲的节奏为每分钟94拍,即一拍为0.64秒。其它节拍与时间的对应关系见表2。
但时,由于T0的最大定时时间只能为131毫秒,因此不可能直接用改变T0的时间初值来实现不同节拍。我们可以用T0来产生10毫秒的时间基准,然后设置一个中断计数器,通过判别中断计数器的值来控制节拍时间的长短。表2中也给出了各种节拍所对应的时间常数。例如对1/4拍音符,定时时间为0.16秒,相应的时间常数为16(即10H);对3拍音符,定时时间为1.92秒,相应时间长数为192(即C0H)。
我们将每一音符的时间常数和其相应的节拍常数作为一组,按顺序将乐曲中的所有常数排列成一个表,然后由查表程序依次取出,产生音符并控制节奏,就可以实现演奏效果。
此外,结束符和体止符可以分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;若查表结果为FFH,则产生相应的停顿效果。
为了产生手弹的节奏感,在某些音符(例如两个相同音符)音插入一个时间单位的频率略有不同的音符。
程序框图如图2所示。
下面给出程序序请单,可直接在TD-III型学习机上演奏,对其它不同型号的学习机,只需相应地改变一下地址即可。本程序演奏的是民歌“八月桂花遍地开”,C调,节奏为94拍/分。读者也可以自行找出一首歌,按表1和表2给定的常数,将乐曲翻译成码表输入机器,而程序不变。本实验方法简便,即使不懂音乐的人,将一首陌生的曲子翻译成代码也是易事,和着机器的演奏学唱一首歌曲,其趣味无穷。
程序清单(略,请参看源程序的说明)。
《无线电》1992年第3期。
下载两个音乐文件的源代码和HEX代码。
硬件连接说明:
随便找一个仿真机或者什么单片机实验板,只要能工作的就行,将程序输入,运行,
然后找个音箱(你计算机旁边应当就有一对吧)拨出插头,插头的前端接在P1。0上,后面部分找根线接单片机的地,就应当有声了,然后怎么改进硬件连接就是你的事了。。。。
因篇幅问题不能全部显示,请点此查看更多更全内容