单片机音乐程序

发布者:名字太长了吗最新更新时间:2013-03-08 来源: 51hei关键字:单片机  音乐程序  89C52 手机看文章 扫描二维码
随时随地手机看文章

利用单片机(或单板机)奏乐大概是无线电爱好者感兴趣的问题之一。本文从单片机的基本发间实验出发,谈谈音乐程序的设计原理,并给出具体实例,以供参考。下面提供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 1EH
REP3L 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 0000H
LJMP MAIN
;---------T0INT--------------
ORG 000BH
LJMP T0INT

;---------T1INT--------------
ORG 001BH
LJMP T1INT
;1.音频发生器
;---------YPFSQ(01)----------
ORG 0030H
T0INT: MOV TL0,R4
MOV TH0,R5
PUSH PSW
PUSH ACC
PUSH 01H
JB LOCF,ROPER
MOV R1,#00H
MOV A,LDYAR
T0LLOP: RRC A
MOV YPBIT,C
XCH A,R1
CJNE A,LDYDSR,T0LNEXT
MOV C,YPBIT
MOV LOUT,C
INC LDYAR
; INC P0
SJMP ROPER
T0LNEXT: XCH A,R1
INC R1
SJMP T0LLOP
ROPER: JB ROCF,T0RETI
MOV R1,#00H
MOV A,RDYAR
T0RLOP: RRC A
MOV YPBIT,C
XCH A,R1
CJNE A,RDYDSR,T0RNEXT
MOV C,YPBIT
MOV ROUT,C
INC RDYAR
; INC P2
SJMP T0RETI
T0RNEXT: XCH A,R1
INC R1
SJMP T0RLOP
T0RETI: POP 01H
POP ACC
POP PSW
RETI
;2.通用时钟[page]
;---------CLOCK(02)----------
T1INT: MOV TL1,#0F0H
MOV TH1,#0D8H
PUSH PSW
PUSH ACC
INC JPCLK
INC GENCLK
INC SNSDCLK
MOV A,SNSDCLK
CJNE A,#0FFH,T1NEXT
CLR SECHSTOF
T1NEXT: INC GEN16T0
MOV A,GEN16T0
CJNE A,#100,T1NEXT0
MOV GEN16T0,#00H
INC GEN16T1
T1NEXT0: INC SETST0
MOV A,SETST0
CJNE A,#100,T1RETI
MOV SETST0,#00H
INC SETST1
MOV A,SETST1
CJNE A,#20,T1RETI
MOV SETST1,#00H
MOV STATU,#00H
T1RETI: POP ACC
POP PSW
RETI
;3.显示子程序
;---------DISPLAY(03)--------
DISPLAY: PUSH ACC
PUSH DPL
PUSH DPH
MOV DPTR,#T_FIGCODE
MOV A,DISNUM0
MOVC A,@A DPTR
MOV SBUF,A
JNB TI,$
CLR TI
MOV A,DISNUM1
MOVC A,@A DPTR
MOV SBUF,A
JNB TI,$
CLR TI
POP DPH
POP DPL
POP ACC
RET
T_FIGCODE:
DB 088H,0EBH,04CH,049H
; 0 1 2 3
DB 02BH,019H,018H,0CBH
; 4 5 6 7
DB 008H,009H,00AH,038H
; 8 9 A B
DB 09CH,068H,01CH,01EH
; C D E F
DB 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 R
DB 029H
; Y
;4.主程序MAIN
;---------MAIN(04)-----------
MAIN: MOV R0,#01H
CLR A
CLRAM: MOV @R0,A
INC R0
CJNE R0,#80H,CLRAM
MOV R0,A
MOV SP,#SBOTM
MOV 08H,#BUFF
;MOV 09H,#BUFF
MOV SCON,#00H
MOV TMOD,#11H
MOV TL1,#0F0H
MOV TH1,#0D8H
SETB EA
SETB ET0
SETB ET1
SETB TR1

START: MOV DPTR,#T_SONGS
RYF: LCALL RYFSUP
MOV A,R7
JZ START
CJNE R7,#0FFH,SYF
JBC NEXTSF,NEXTSCL
MOV A,STATU
JNZ GONSBQ
MOV A,BUFF0
JNZ MPSQCL
LCALL PAQSCL
SJMP MQNFD
MPSQCL: LCALL PSQSCL
MQNFD: LCALL QNFDSUP
MOVPJRYF: INC DPTR
INC DPTR
SJMP RYF
NEXTSCL: LCALL CSBESTOJG
JB CSBESTOF,CALLPSCL
LCALL PAQSCL
SJMP MOVPJRYF
CALLPSCL: LCALL PSQSCL
SJMP MOVPJRYF
GONSBQ: LCALL CSDPTR
INC DPTR
INC DPTR
SJMP MOVPJRYF
SYF: CJNE R6,#0FFH,CALLPLAY
LCALL REPCLSUP
SJMP MOVPJRYF
CALLPLAY: LCALL YFDSUP
LCALL PLAY
SJMP MOVPJRYF
;5.读音符子程序
;---------RYFSUP(05)--------
RYFSUP: CLR A
MOVC A,@A DPTR
MOV R6,A
MOV A,#01H
MOVC A,@A DPTR
MOV R7,A
RET
;6.统唱曲首处理
;---------PAQSCL(06)--------
PAQSCL: MOV CSN,R6
INC DPTR
INC DPTR
LCALL RYFSUP
MOV 02H,R6
MOV 03H,R7
RET
;7.存唱曲首处理
;---------PSQSCL(07)--------
PSQSCL: PUSH PSW
SETB RS0
CLR RS1
PSQC7E: CJNE R0,#7EH,PSQNEXT
PSQNEXT: JC PSQNEXT1
MOV R0,#BUFF
SJMP PSQC7E
PSQNEXT1: MOV A,@R0
JNZ PSQNEXT2
INC R0
INC R0
INC R0
SJMP PSQC7E
PSQNEXT2: MOV CSN,@R0
INC R0
MOV 02H,@R0
INC R0
MOV 03H,@R0
INC R0
POP PSW
LCALL CSDPTR
INC DPTR
INC DPTR
RET
;8.曲号闪显子程序
;---------QNFDSUP(08)-------
QNFDSUP: PUSH ACC
MOV GEN16T0,#00H
MOV GEN16T1,#00H
QNGON: LCALL CSNSDISN
LCALL DISPLAY
MOV GENCLK,#00H
QNWAIT: MOV A,GENCLK
CJNE A,#35,QNWAIT
MOV DISNUM0,#20H
MOV DISNUM1,#20H
LCALL DISPLAY
MOV GENCLK,#00H
QNWAIT1: MOV A,GENCLK
CJNE A,#15,QNWAIT1
MOV A,GEN16T1
CJNE A,#02,QNGON
POP ACC
RET
;9.曲号送显示寄存器
;---------CSNSDISN(09)------
CSNSDISN: MOV A,CSN
ANL A,#0FH
LCALL CSBESTOJG
JNB CSBESTOF,NADP
ADD A,#10H
NADP: MOV DISNUM0,A
MOV A,CSN
SWAP A
ANL A,#0FH
MOV DISNUM1,A
RET
;10.当前曲是否被存储判断
;---------CSBESTOJG(10)-----
CSBESTOJG:PUSH ACC
PUSH PSW
MOV A,BUFF0
JZ CLRCSTOF
MOV R0,#BUFF
CSBCMPCSN:MOV A,@R0
CJNE A,CSN,CSBGSCAN
SETB CSBESTOF
SJMP CSBRET
CSBGSCAN: INC R0
INC R0
INC R0
CJNE R0,#7EH,CSBNEXT
CSBNEXT: JC CSBCMPCSN
CLRCSTOF: CLR CSBESTOF
MOV R0,#BUFF
CSBCMP0: MOV A,@R0
JZ CSBRET
INC R0
INC R0
INC R0
CJNE R0,#7EH,CSBNEXT1
CSBNEXT1: JC CSBCMP0
CSBRET: POP PSW
POP ACC
RET
;11.找当前曲首址
;---------CSDPTR(11)--------
CSDPTR: MOV DPTR,#T_SONGS
CSDSCAN: LCALL RYFSUP
CJNE R7,#0FFH,CSDNEXT
MOV A,R6
CJNE A,CSN,CSDNEXT
SJMP CSDRET
CSDNEXT: INC DPTR
INC DPTR
SJMP CSDSCAN
CSDRET: RET
;12.重复段处理子程序
;---------REPCLSUP(12)------
REPCLSUP: MOV A,R7
ANL A,#0FH
CJNE A,#02H,CMPA3
MOV A,R7
SWAP A
ANL A,#0FH
JNZ H4CMP1
JNB REP0F,REPRET0
CLR REP0F
MOV DPL,REP0L
MOV DPH,REP0H
REPRET0: RET
H4CMP1: CJNE A,#01H,H4CMP2
JNB REP1F,REPRET
CLR REP1F
MOV DPL,REP1L
MOV DPH,REP1H
RET
H4CMP2: CJNE A,#02H,H4CMP3
JNB REP2F,REPRET
CLR REP2F
MOV DPL,REP2L
MOV DPH,REP2H
RET
H4CMP3: CJNE A,#03H,REPRET
JNB REP3F,REPRET
CLR REP3F
MOV DPL,REP3L
MOV DPH,REP3H
RET
CMPA3: CJNE A,#03H,REPRET
MOV A,R7
SWAP A
ANL A,#0FH
JNZ H4VS1
SETB REP0F
MOV REP0L,DPL
MOV REP0H,DPH
SJMP SREPHAD
H4VS1: CJNE A,#01H,H4VS2
SETB REP1F
MOV REP1L,DPL
MOV REP1H,DPH
SJMP SREPHAD
H4VS2: CJNE A,#02H,H4VS3
SETB REP2F
MOV REP2L,DPL
MOV REP2H,DPH
SJMP SREPHAD
H4VS3: CJNE A,#03H,REPRET
SETB REP3F
MOV REP3L,DPL
MOV REP3H,DPH
SREPHAD: MOV 09H,A
LCALL CSDPTR
REPGON: INC DPTR
INC DPTR
LCALL RYFSUP
CJNE R6,#0FFH,REPGON
MOV A,R7
SWAP A
ANL A,#0FH
CJNE A,09H,REPGON
REPRET: RET
;13.音符显示子程序
;---------YFDSUP(13)--------
YFDSUP: MOV A,STATU
JNZ YFDRET
JB SECHSTOF,YFDRET
JNB CUYFD,YFSLED
XZFCLD: MOV DISNUM0,#20H
MOV DISNUM1,#20H
SJMP YFDSPLAY
YFSLED: MOV A,R6
JZ XZFCLD
ANL A,#0FH
PUSH DPL
PUSH DPH
MOV DPTR,#T_YFDCOD
MOVC A,@A DPTR
MOV DISNUM0,A
POP DPH
POP DPL
MOV A,R6
SWAP A
ANL A,#0FH
MOV DISNUM1,A
YFDSPLAY: LCALL DISPLAY
YFDRET: RET
T_YFDCOD: DB 20H ;--
DB 01H ; 1
DB 02H ; 2
DB 03H ; 3
DB 04H ; 4
DB 05H ; 5
DB 06H ; 6
DB 07H ; 7
DB 11H ;#1
DB 12H ;#2
DB 14H ;#4
DB 15H ;#5
DB 16H ;#6
;14.唱音符子程序
;---------PLAY(14)----------
PLAY: MOV A,R6
JZ PCOSPECL
PUSH DPL
PUSH DPH
MOV DPTR,#T_SD
ANL A,#0FH
MOVC A,@A DPTR
XCH A,R6
SWAP A
ANL A,#0FH
MOV B,#12
MUL AB
ADD A,R6
ADD A,R2
RL A
MOV R6,A
MOV DPTR,#T_RAN
MOVC A,@A DPTR
MOV TH0,A
MOV R5,A
MOV A,R6
INC A
MOVC A,@A DPTR
MOV TL0,A
MOV R4,A
POP DPH
POP DPL
SETB TR0
PCOSPECL: LCALL COSPECL
PJPWAIT: MOV JPCLK,#00H
PDELAY: LCALL KCXCL
JB NEXTSF,PRET
MOV A,JPCLK
CJNE A,01H,PNEXT
PNEXT: JC PDELAY
DJNZ R7,PJPWAIT
PRET: CLR TR0
RET
;---------TABSD-------------
T_SD: DB 01h ;useless
DB 01H
DB 03H
DB 05H
DB 06H
DB 08H
DB 0AH
DB 0CH
DB 02H
DB 04H
DB 07H
DB 09H
DB 0bH
;---------TABRAN------------
T_RAN: DW 0F111H ;useless
dw 0f111h ; area 0
dw 0f1e8h
dw 0f2b2h
dw 0f373h
dw 0f426h
dw 0f4eeh
dw 0f571h
dw 0f609h
dw 0f699h
dw 0f71fh
dw 0f79fh
dw 0f817h
dw 0f889h ; area 1
dw 0f8f4h
dw 0f95ah
dw 0f9b9h
dw 0fa13h
dw 0fa68h
dw 0fab9h
dw 0fb04h
dw 0fb4ch
dw 0fb90h
dw 0fbcfh
dw 0fc0ch
dw 0fc45h ;area 2
dw 0fc7ah
dw 0fcadh
dw 0fcdch
dw 0fd0ah
dw 0fd34h
dw 0fd5ch
dw 0fd82h
dw 0fda6h
dw 0fdc8h
dw 0fde8h
dw 0fe06h
dw 0fe22h ; area 3
dw 0fe3dh
dw 0fe56h
dw 0fe6eh
dw 0fe85h
dw 0fe9ah
dw 0feaeh
dw 0fec1h
dw 0fed3h
dw 0fee3h
dw 0fef4h
dw 0ff02h
dw 0ff11h ;area 4
dw 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.共速处理[page]
;---------COSPECL(15)-------
COSPECL: MOV R1,03H
MOV A,COSPEEDN
JZ COSPRET
PUSH COSPEEDN
MOV A,R1
COSPEGON: MOV B,#08H
MUL AB
CLR C
SUBB A,R1
JNC COSPNEXT
DEC B
COSPNEXT: MOV R6,#03H
DIV8: CLR C
XCH A,B
RRC A
XCH A,B
RRC A
DJNZ R6,DIV8
MOV R1,A
DJNZ COSPEEDN,COSPEGON
POP COSPEEDN
MOV A,R1
JNZ COSPRET
MOV R1,#01H
COSPRET: RET
;16.键盘查询处理
;---------KCXCL(16)---------
KCXCL: LCALL KSET
LCALL KALT0
LCALL KALT1
JNB KSETF,KNEXT0
LCALL KSETCL
KSETSTC: MOV SETST0,#00H
MOV SETST1,#00H
SETB KBDISF
SJMP KDIS
KNEXT0: JNB KALT0F,KNEXT1
LCALL KALT0CL
SJMP KSETSTC
KNEXT1: JNB KALT1F,KDIS
LCALL KALT1CL
SJMP KSETSTC
KDIS: MOV A,STATU
JNZ KSSNSD
JNB SECHSTOF,KRET
KSSNSD: JNB KBDISF,KRET
CLR KBDISF
LCALL DISPLAY
KRET: RET
;17.KSET键是否按下查询
;---------KSET(17)----------
KSET: SETB SET
JB SET,CSETRET
MOV GENCLK,#00H
SETLOP: MOV A,GENCLK
CJNE A,#02,SETLOP
SETB SET
JB SET,CSETRET
CLR TR0
SETWAIT: SETB SET
JNB SET,SETWAIT
MOV GENCLK,#00H
SETLOP1: MOV A,GENCLK
CJNE A,#02,SETLOP1
SETB TR0
SETB KSETF
RET
CSETRET: CLR KSETF
RET
;18.KALT0键是否按下查询
;---------KALT0(18)---------
KALT0: SETB ALT0
JB ALT0,CALT0RET
MOV GENCLK,#00H
ALT0LOP: MOV A,GENCLK
CJNE A,#02,ALT0LOP
SETB ALT0
JB ALT0,CALT0RET
CLR TR0
ALT0WAIT: SETB ALT0
JNB ALT0,ALT0WAIT
MOV GENCLK,#00H
ALT0LOP1: MOV A,GENCLK
CJNE A,#02,ALT0LOP1
SETB TR0
SETB KALT0F
RET
CALT0RET: CLR KALT0F
RET
;19.KALT1键是否按下查询
;---------KALT1(19)---------
KALT1: SETB ALT1
JB ALT1,CALT1RET
MOV GENCLK,#00H
ALT1LOP: MOV A,GENCLK
CJNE A,#02,ALT1LOP
SETB ALT1
JB ALT1,CALT1RET
CLR TR0
ALT1WAIT: SETB ALT1
JNB ALT1,ALT1WAIT
MOV GENCLK,#00H
ALT1LOP1: MOV A,GENCLK
CJNE A,#02,ALT1LOP1
SETB TR0
SETB KALT1F
RET
CALT1RET: CLR KALT1F
RET
;20.SET键处理
;---------KSETCL(20)--------
KSETCL: INC STATU
MOV A,STATU
CJNE A,#07H,STATUDIS
MOV STATU,#00H
STATUDIS: MOV DISNUM0,#23H
MOV DISNUM1,STATU
RET
;21.KALT0键处理
;---------KALT0CL(21)-------
KALT0CL: MOV A,STATU
JNZ CASEB1
KA0S0GO: INC DPTR
INC DPTR
LCALL RYFSUP
MOV A,R7
JNZ EQUFF
MOV DPTR,#T_SONGS
SJMP KA0NEXT
EQUFF: INC A
JNZ KA0S0GO
KA0NEXT: LCALL RYFSUP
MOV CSN,R6
LCALL CSNSDISN
MOV A,DPL
CLR C
SUBB A,#02H
JNC KA0NEXT1
DEC DPH
KA0NEXT1: MOV DPL,A
CLR REP0F
CLR REP1F
CLR REP2F
CLR REP3F
SETB NEXTSF
SETB SECHSTOF
RET
CASEB1: CJNE A,#01H,CASEB2
INC LDYDSR
MOV A,LDYDSR
CJNE A,#04H,LDYDSL4
MOV LDYDSR,#00H
LDYDSL4: MOV DISNUM0,LDYDSR
MOV DISNUM1,#26H
RET

HCOSPEEDN EQU 12H
CASEB2: CJNE A,#02H,CASEB3
MOV A,COSPEEDN
CJNE A,#HCOSPEEDN,KA0NEXT4
KA0NEXT4: JNC KA0NEXT5
INC COSPEEDN
KA0NEXT5: MOV SPENR,COSPEEDN
LCALL SPENSDISN
RET
CASEB3: CJNE A,#03H,CASEB4
CLR SPEEDF
LCALL SPEEDCL
RET
CASEB4: CJNE A,#04H,CASEB5
CLR TONEF
LCALL TONECL
RET
CASEB5: CJNE A,#05H,CASEB6
CPL LOCF
JNB LOCF,KA0NEXT2
MOV DISNUM0,#24H
SJMP KA0NEXT3
KA0NEXT2: MOV DISNUM0,#25H
KA0NEXT3: MOV DISNUM1,#26H
RET
CASEB6: CJNE A,#06H,KA0RET
CPL CUYFD
JNB CUYFD,KA0NEXT6
MOV DISNUM0,#24H
SJMP KA0NEXT7
KA0NEXT6: MOV DISNUM0,#25H
KA0NEXT7: MOV DISNUM1,#28H
KA0RET: RET
;22.速度数送显示寄存器
;---------SPENSDISN(22)----
SPENSDISN:MOV A,SPENR
ANL A,#0FH
MOV DISNUM0,A
MOV A,SPENR
SWAP A
ANL A,#0FH
MOV DISNUM1,A
RET
;23.速度处理
;---------SPEEDCL(23)------
HSPEED EQU 02H;
LSPEED EQU 50H;
SPEEDCL: JB SPEEDF,DNSPEED
CJNE R3,#HSPEED,SCLNEXT
SCLNEXT: JC SCLNEXT1
DEC R3
SJMP SCLNEXT1
DNSPEED:
CJNE R3,#LSPEED,SCLNEXT2
SCLNEXT2: JNC SCLNEXT1
INC R3
SCLNEXT1: LCALL CSBESTOJG
JNB CSBESTOF,SCLNEXT3
INC R0
INC R0
MOV @R0,03H
SCLNEXT3: LCALL COSPECL
MOV SPENR,R1
LCALL SPENSDISN
RET
;24.音调处理
;---------TONECL(24)---------
;LTONE EQU 00 ;C
HTONE EQU 11 ;B
TONECL: JB TONEF,DNTONE
CJNE R2,#HTONE,TCLNEXT0
TCLNEXT0: JNC TCLNEXT
INC R2
SJMP TCLNEXT
DNTONE: MOV A,R2
JZ TCLNEXT
DEC R2
TCLNEXT: LCALL CSBESTOJG
JNB CSBESTOF,TCLNEXT1
INC R0
MOV @R0,02H
TCLNEXT1: PUSH DPL
PUSH DPH
MOV DPTR,#T_TONDISC
MOV A,R2
RL A
MOVC A,@A DPTR
MOV DISNUM1,A
MOV A,R2
RL A
INC A
MOVC A,@A DPTR
MOV DISNUM0,A
POP DPH
POP DPL
RET
T_TONDISC:DW 200CH ; C
DW 210CH ;#C
DW 200DH ; D
DW 210DH ;#D
DW 200EH ; E
DW 200FH ; F
DW 210FH ;#F
DW 2022H ; G
DW 2122H ;#G
DW 200AH ; A
DW 210AH ;#A
DW 200BH ; B
;25.KALT1键处理
;---------KALT1CL(25)--------
KALT1CL: MOV A,STATU
JNZ CASE1
LCALL CSBESTOJG
JNB CSBESTOF,KA1NEXT
MOV @R0,#00H
DEC BUFF0
SJMP KA1NEXT2
KA1NEXT: CJNE R0,#7EH,KA1NEXT1
KA1NEXT1: JNC KA1NEXT2
MOV @R0,CSN
INC R0
MOV @R0,02H
INC R0
MOV @R0,03H
INC BUFF0
KA1NEXT2: LCALL CSNSDISN
SETB SECHSTOF
RET[page]
CASE1: CJNE A,#01H,CASE2
INC RDYDSR
MOV A,RDYDSR
CJNE A,#04H,RDYDSL4
MOV RDYDSR,#00H
RDYDSL4: MOV DISNUM0,RDYDSR
MOV DISNUM1,#27H
RET
CASE2: CJNE A,#02H,CASE3
MOV A,COSPEEDN
JZ KA1NEXT5
DEC COSPEEDN
KA1NEXT5: MOV SPENR,COSPEEDN
LCALL SPENSDISN
RET
CASE3: CJNE A,#03H,CASE4
SETB SPEEDF
LCALL SPEEDCL
RET
CASE4: CJNE A,#04H,CASE5
SETB TONEF
LCALL TONECL
RET
CASE5: CJNE A,#05H,CASE6
CPL ROCF
JNB ROCF,KA1NEXT3
MOV DISNUM0,#24H
SJMP KA1NEXT4
KA1NEXT3: MOV DISNUM0,#25H
KA1NEXT4: MOV DISNUM1,#27H
RET
CASE6: CJNE A,#06H,KA1RET
MOV DISNUM0,#23H
MOV DISNUM1,#06H
KA1RET: RET
;========= 乐曲表============
;---------SONGS--------------
T_SONGS: 乐曲表表首
dw 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 Hu
DW 0715H
DW 0FF21H ;REP21
DW 0FF01H ;REP01
DW 2102H
DW 2202H
DW 2302H
DW 2102H
DW 0FF02H ;REP02
DW 0FF03H ;REP03
DW 2302H
DW 2402H
DW 2504H
DW 2302H
DW 2402H
DW 2504H
DW 0FF11H ;REP11
DW 2501H
DW 2601H
DW 2501H
DW 2401H
DW 2302H
DW 2102H
DW 0FF12H ;REP12
DW 0FF13H ;REP13
DW 2202H
DW 1502H
DW 2104H
DW 2202H
DW 1502H
DW 2104H
DW 0FF22H ;REP22
DW 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给定的常数,将乐曲翻译成码表输入机器,而程序不变。本实验方法简便,即使不懂音乐的人,将一首陌生的曲子翻译成代码也是易事,和着机器的演奏学唱一首歌曲,其趣味无穷。

程序清单(略,请参看源程序的说明)。

点击浏览下一页

 

硬件连接说明:

随便找一个仿真机或者什么单片机实验板,只要能工作的就行,将程序输入,运行,然后找个音箱(你计算机旁边应当就有一对吧)拨出插头,插头的前端接在P1。0上,后面部分找根线接单片机的地,就应当有声了,然后怎么改进硬件连接就是你的事了。。。。

关键字:单片机  音乐程序  89C52 引用地址:单片机音乐程序

上一篇:单片机音乐盒设计
下一篇:C51函数返回值传递规则是什么?

推荐阅读最新更新时间:2024-03-16 13:20

基于C8051F920单片机在太阳能充电系统中的设计
在世界能源短缺、环境污染日益严重的今天,如何有效地利用清洁的太阳能正在成为各国可持续发展的能源战略。目前,大部分照明设备仍以传统能源来照明,所以充分利用太阳能作为照明设备的能源供给,在节约能源、保护环境等方面具有重要意义。 为此,设计了具有太阳能供电功能的金卤灯控制器。该控制器既具有金卤灯电子镇流器功能,又具有太阳能充电器功能。该控制器作为电子镇流器,与传统镇流器相比,具有功率因素高,运行稳定,体积小等优点。作为具有太阳能供电功能的控制器,根据设定,控制器白天控制太阳能充电系统对12 V/100 Ah蓄电池充电,晚上使金卤灯工作。由于太阳能光伏板在自然环境下容易受到雷击损坏,所以该控制器在设计时还兼顾了防雷击的保护功能。
[单片机]
基于C8051F920<font color='red'>单片机</font>在太阳能充电系统中的设计
一种基于单片机的高精度超声波多路同步测距系统设计
0 引言   超声波测距作为一种非接触性的检测方法,因其结构简单紧凑、可靠性高、价格低廉、实时性强等优点,近年来已经得到了广泛应用,如液位测量,修路过程中路面平整检测,汽车倒车雷达,机器人辅助视觉识别系统等。但因超声波在空气中传播时受到诸如环境温度、湿度、风速等影响,传统的超声波测距系统精度普遍较低。文献 采用了在系统中增加硬件温度补偿模块仅在一定程度上可以避免因环境温度变化带来的测量误差。文献 中采用小波等处理算法,也并不能弥补系统本质上的缺陷。因此,研究了一种控制精度高,适用范围宽的高精度多路同步超声波测距系统。   1 超声波测距工作原理与结构   1.1 工作原理   谐振频率高于20 kHz的声波被称为超声波。超声波
[单片机]
一种基于<font color='red'>单片机</font>的高精度超声波多路同步测距系统设计
简单的温度指示器使用基于RISC的MCU
非常简单的温度指示器可以在8位RISC微控制器周围构建(参见图)。来自温度感应器的数据由MCU处理并且用于显示温度。在本电路中使用的MAX6577温度感应器可以测量范围在-40°C至125°C之间的温度。它几乎不需要其他外部元件。 这个感应器可以将温度转换成其输出信号频率与绝对温度(K)成比例的方形波。如果这个频率已经测量出来了,计算温度就会变得相当容易。这可以通过不同的时间测量电路或者MCU中提供的定时器来实现。 这个电路使用AVR AT90S4433低成本MCU用来处理感应器数据和显示温度。在其他器件中,这个MCU配有4千字节的系统内可编程闪存、128字节的SRAM、128字节的系统可编程EEPROM、一个六通道
[单片机]
简单的温度指示器使用基于RISC的<font color='red'>MCU</font>
STM32单片机UART发送配置的步骤及方法
字符发送的过程描述:在UART的发送过程中先将数据输入到发送数据寄存器中(TDR)此时(TXE)被硬件置1,之后TDR寄存器将数据串行移入到发送移位寄存器中,将数据在TX端口发送,此时(TC)被硬件置1。发送与接收是逆过程。 UART发送配置步骤: 1.通过USART_CR1寄存器上置位UE来激活USART。 2.编程USART_CR1的M位来定义字长。 3.在USART_CR2中编程停止位的位数。 4.如果采用多缓冲器通信,配置USART_CR3中的DMA使能位(DMAT)。按多缓冲器通信中的描述配置DMA寄存器。 5.利用USART_BRR寄存器选择要求的波特率。 6. 设置USART_CR1中的TE位,发送一个空闲帧作为
[单片机]
STM32<font color='red'>单片机</font>UART发送配置的步骤及方法
MCS-51单片机存储地址空间划分
1.前言 MCS-51的存储器有片内RAM、片外RAM 和 ROM 三个空间。 MCS-51单片机在物理结构上有四个存储空间 1、片内程序存储器(片内ROM) 2、片外程序存储器(片外ROM) 3、片内数据存储器(片内RAM) 4、片外数据存储器(片外RAM) 在逻辑上(即从用户的角度上)MCS-51单片机有三个存储空间 1、片内外统一编址的64K的程序存储器(ROM)地址空间(MOVC) 2、256B的片内数据存储器(片内RAM)的地址空间(MOV) 3、以及64K片外数据存储器(片外RAM)的地址空间(MOVX) 注:在访问三个不同的逻辑空间时,应采用不同形式的指令以产生不同的存储器空间的选通信号。 2.存储空间划
[单片机]
STC12C2052AD单片机做的红外学习遥控器
// 中断函数注意养成指定寄存器组的习惯 //不同优先级的中断程序绝对不能使用同一组寄存器 /*****编程时防止中断把寄存器中的数据改变的解决方法是给中断指定寄存器, 同优先级的使用同一组没事。 1、写中断程序一定要用using语句指定寄存器组。第1、2、3组都可以,不能是0. 2、51单片机的中断有两个优先级。一个中断不会打断另一个相同优先级的中断。 这样相同级别中断可以使用同一个组。比如:低优先级的中断函数都 用 using 1,高优先级的中断都用 using 2 。这样不会冲突。 下面是一个正常的例子: C程序: void int0() interrupt 0 using 1 默
[单片机]
STC12C2052AD<font color='red'>单片机</font>做的红外学习遥控器
SafeTI编译器资质审核套件 配合MCU简化安全应用开发
近日,德州仪器 (TI) 宣布推出最新 SafeTI 编译器资质审核套件,进一步丰富其 SafeTI 设计套件。该 SafeTI 编译器资质审核套件不但可帮助客户审核 TI ARM® C/C++ 编译器的使用是否符合 IEC 61508 与 ISO 26262 等功能安全标准,同时还有助于最大限度提高其功能性及性能。该套件是 SafeTI 设计套件的一个组件,主要用于与 TI 基于 ARM Cortex-R4 的 Hercules 安全微控制器 (MCU) 配合使用,帮助客户简化功能安全应用开发。 SafeTI 编译器资质审核套件使用了Validas 开发的模块化工具资质审核方法,Validas是一家专注于嵌入式系统软件资质审
[单片机]
单片机进制转换
  一、正数   在高速发展的现代社会,计算机浩浩荡荡地成为了人们生活中不可缺少的一部分,帮助人们解决通信,联络,互动等各方面的问题。今天我就给大家讲讲与计算机有关的“进制转换”问题。   我们以(25.625)(十)为例讲解一下进制之间的转化问题。 1. 十 ----- 二   给你一个十进制,比如:6,如果将它转换成二进制数呢?   10进制数转换成二进制数,这是一个连续除2的过程:   把要转换的数,除以2,得到商和余数,   将商继续除以2,直到商为0。最后将所有余数倒序排列,得到数就是转换结果。   听起来有些糊涂?我们结合例子来说明。比如要转换6为二进制数。   “把要转换的数,除以2,得到商
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved