当前位置:首页 > 单片机课程设计-音乐彩灯控制器 - 图文
曲调值 调4/4 调3/4 调2/4
DELAY 125毫秒 187毫秒 250毫秒
曲调值 调4/4 调3/4 调2/4
DELAY 62毫秒 94毫秒 125毫秒
表3-3-3 各调节拍的时间设定表
四分之一拍延时代码设计: 1/4拍的延迟时间=187毫秒 DELAY: MOV R7,#2 D2: MOV R4,#187 D3: MOV R3,#248 DJNZ R3,$ DJNZ R4,D3 DJNZ R7,D2 RET
4.4 音乐代码实现
4.4.1音乐代码库的建立方法
(1)先找出乐曲的最低音和最高音范围,然后确定音符表T的顺序。 (2)把T值表建立在TABLE1,构成发音符的计数值放在“TABLE”。 (3)简谱码(音符)为高位,节拍为(节拍数)为低4位,音符节拍码放在程序的“TABLE”处。
(4)音符节拍码00H为音乐结束标记。 4.4.2选曲
在一个程序中,需要演奏两首或两首以上的歌曲时,音乐代码库的建立有两种方法:
(1)将每首歌曲建立相互独立的音符表T和发音符计数值TABLE。 (2)在建立公用音符表T后,再写每首歌的发音计数值TABLE中的代码 不管采用那种方法,每首歌曲结束时,在TABLE中均需加上音乐结束符00H。
第 10页 共 20页
4.5音乐彩灯程序
OUT BIT P3.6 ;***定义音频输出端口,P3.6 N EQU 3 ;***歌曲总数 OUT_NUM EQU P0 ORG 0000H AJMP MAIN ORG 0003H
AJMP LAST_SONG ;***外部中断0用于接上一曲歌按键 ORG 000BH
AJMP F_T0
;***定时器0用于定时,作音符发生器用 ORG 0013H
AJMP NEXT_SONG ;***外部中断1接下一曲歌按键 ORG 001BH
AJMP START_PAUSE
;***定时器1用计数,这里用作中断,接开始/暂停键,初值为0ffH,方式2 ORG 0030H
MAIN: MOV SP,#60H MOV DPTR,#TABLE
;***DPRT指向每首歌曲的入口地址的地址。 MOV R0,#30H
;***R0中存入数据30H,这里在以30H开始的单元 ;***存放每首歌曲的入口地址,其中30H,31H存放 歌曲的节拍入口地址,32H,33H存放;歌曲音符入口地址,每首歌占用四个存储存单元。 MOV R5,#00H
MOV R6,#1
SET_TAB:MOV A,R5
;***设置每首歌曲的入口信息,存放在以30H开始 的存储单元中。
MOVC A,@A+DPTR MOV @R0,A INC R5 INC R0 MOV A,R5
MOVC A,@A+DPTR
;***R5中存放表TABLE中正在执行操作的序号 ;***R6存放正在设置入口信息的歌曲数
MOV @R0,A INC R5 INC R0 MOV A,R5
MOVC A,@A+DPTR MOV @R0,A INC R0 INC R5 MOV A,R5
MOVC A,@A+DPTR MOV @R0,A INC R0 INC R5
INC R6 ;***设置完一首歌曲后,歌曲数加1 CJNE R6,#N+1,SET_TAB
;***是否设置完,没有便继续,否则进行下面的操
作
;***对中断,计数器的相关参数进行设置 MOV TMOD, #61H
;***计数器0工作方式1,计数器1工作方式2 MOV TH1,#0FFH
MOV TL1,#0FFH
;***给计数器1置初值0FFH,又由于是工作方式所 以计数器计数为1,相当于一外部中断。 SETB ET1
;***允许计数器1中断 SETB ET0
;***允许计数器具0中断 CLR PT0 ;***计数器0为低优先级 SETB PT1
;***计数器1为高优先级 SETB IT0 ;***外部中断0为跳沿触发 SETB PX0 ;***高优先级
SETB IT1 ;***外部中断1为跳沿触发 SETB PX1 ;***高优先级
SETB EX1 ;***允许外部中断1中断
第 11页 共 20页
;***数码管显视当前所放歌曲曲数
SETB EX0
MOV R0,A MOV DPH,@R0 INC R0 MOV DPL,@R0
;定时器1开始工
INC R0 MOV A,R4 INC R4
MOVC A,@A+DPTR ;***放在A中
MOV P1,A
;***节奏彩灯
;******************************************* JZ END0 唱
;***若为0,则表示为休止符,不唱,本次音符不 MOV R1,A ANL A,#0FH
MOV R2,A MOV A,R1 SWAP A ANL A,#0FH JNZ SING ;***音符不为0,唱
CLR TR0 ;***为0,不唱,关频率发生器
SJMP SING1
SING: DEC A ;***开始唱,进行相应的数据处理 MOV R3,A RL A
MOV DPH,@R0 INC R0 MOV DPL,@R0 INC R0
MOVC A,@A+DPTR MOV 21H,A MOV TH0,A MOV A,R3 RL A INC A
MOVC A,@A+DPTR MOV 20H,A MOV TL0,A SETB TR0
第 12页 共 20页
;***允许外部中断定0中断 SETB EA ;***开中断总开关
SETB TR1 作,作中断用 SETB OUT ;***设置结束 CLR F0
;***设置F0=0,用来作暂停/的标置位用 MOV 22H,#01H
;***22H单元中存放正在播放的歌曲编号 MOV DPTR,#OUT_TAB MOV A,22H MOVC A,@A+DPTR MOV OUT_NUM,A
MOV P2,#0FEH
;***数码管位选
MOV R7,#00H ;***R7中存放歌曲总信息的入口地址 START0:MOV R4,#00H
;***R4存放当前正在播放歌曲的第几个节拍数 MOV R0,#30H
MOV A,R7
;***将歌曲的节拍表的入口地址送到DPTR ADD A,R0 MOV R0,A MOV DPH,@R0 INC R0 MOV DPL,@R0 INC R0 MOV A,R4 INC R4
MOVC A,@A+DPTR
;***取出第一节拍数,其实第一个节拍不是歌曲的 第一个节拍而是表示几分音符
MOV 26H,A
;***将取出的音符数+节拍数保存在职26H单元中 NEXT: MOV R0,#30H ;***开始取出歌曲的第一个据 MOV A,R7 ADD A,R0
;***30H开始的单元中存放歌曲的入口信息 ;***将正在播放的歌曲编号送数码管显视 ;***音频输出端口初始化
;***不为0,取出节拍数
;***开唱
SING1:LCALL DELAY ;***每个音符唱多久 JB F0,FOR FOR: CLR TR0 ;***暂停,不唱 JB F0,$ ;***等待播放
AJMP NEXT ;***开始播放
END0: CLR TR0 ;***不唱
MOV A,22H CJNE A,#N,WW MOV 22H,#01H MOV R7,#00H
MOV OUT_NUM,#06H AJMP WWW
;***唱完处理
;***是不是全部歌曲都唱完
;***全部唱完,则从第一首开始再唱
;是否暂停,
AJMP NEXT
;没有暂停,继续
;***频率产生 RETI
NEXT_SONG: PUSH ACC PUSH DPH
PUSH DPL
CLR EA ;***关中断
MOV A,22H
CJNE A,#N,Q MOV R7,#00H MOV 22H,#01H AJMP BACK
;***是最后一首吗?
;***是最后一首,则R7指向第一首,演唱第一首
;***下一曲中断程序处理,保护现场
Q: INC 22H 加1
MOV A,R7
ADD A,#4 MOV R7,A
;***不是最后一首,唱下一首,R7内容加4,歌曲数
;***数码管显视第一首歌曲编号 BACK: MOV R4,#00H WW: MOV A,R7 ADD A,#4 MOV R7,A INC 22H
CLR EA PUSH DPH PUSH DPL MOV A,22H
MOV DPTR,#OUT_TAB MOVC A,@A+DPTR MOV OUT_NUM,A POP DPL POP DPH
MOV A,22H
;***数码管显视相应的歌曲编号
MOV DPTR,#OUT_TAB MOVC A,@A+DPTR MOV OUT_NUM,A
;***没有全部唱完,唱下一首,歌曲的入口信息调整
;******************************************* MOV B,R0
;***对下首要演唱的歌曲的几分拍进行调整,同时对R0中的内容进行保护 MOV R4,#00H MOV R0,#30H MOV A,R7 ADD A,R0 MOV R0,A MOV DPH,@R0 INC R0 MOV DPL,@R0 INC R0 MOV A,R4 INC R4
MOVC A,@A+DPTR
MOV 26H,A
;***结果存入26H单元中
第 13页 共 20页
;***数码管显视相应的歌曲编号
WWW: SETB EA
AJMP START0 ;***开始下一首的演唱
F_T0: MOV TH0,21H ;***定时器0置初值 MOV TL0,20H CPL OUT
共分享92篇相关文档