标题:
音乐盒设计 驱动蜂鸣器
[打印本页]
作者:
xky199719
时间:
2017-12-14 20:02
件3:音乐程序
shuzhi EQU 3fh ;选曲目的地址
song EQU p1.2 ;扬声器播放
play EQU p3.0 ;播放停止键
addone EQU p3.1 ;曲目加一键
subone EQU p3.2 ;曲目减一键
dul EQU P1 ;段选
wel EQU P2 ;位选
ORG 0000H
LJMP START
ORG 000BH ;定时器0溢出中断入口地址
AJMP cont
ORG 0013H ;外部中断一入口地址
AJMP pause ;指向外部中断程序
ORG 0100H
START:
MOV SP,#50H
MOV TH0,#0DBH ;定时器赋初值
MOV TL0,#0FFH
MOV TMOD,#01H ;设定T1工作于方式2
MOV IE,#86H ;开中断
MOV TCON,#00H
MOV R0,#00H
MOV shuzhi,#00H
(是否顺序播放音乐)
MAIN:
JNB play,first ;判断P3.0键是否按下
SJMP MAIN
first:
ACALL del20
JNB play,first
MOV shuzhi,#00H
MOV dul,#06H ;共阴数码管显示1
MOV wel,#80H
MOV DPTR,#dat1 ;dat1首地址赋给DPTR
ACALL music0
ACALL next
RET
next:
INC shuzhi
MOV A,shuzhi
CJNE A,#01,LOOP3 ;A是否=1,不等就跳转到LOOP3
MOV DPTR,#dat2 ;表2首地址送DPTR
MOV dul,#5BH ;显示数值2
MOV wel,#80H
ACALL music0
INC A
LOOP3:
CJNE A,#02,LOOP4 ;A是否=2,不等就跳转到LOOP4
MOV DPTR,#dat3 ;表3首地址送DPTR
MOV dul,#4FH ;显示数值3
MOV wel,#80H
ACALL music0
INC A
LOOP4:
CJNE A,#03,next
ACALL first
RET
(按键播放上一首音乐)
last:
DEC shuzhi
MOV a,shuzhi
CJNE a,#02,last1
MOV dptr,#dat3
MOV dul,#4Fh
MOV wel,#80h
ACALL music0
last1: cjne a,#01,last2
MOV dptr,#dat2
MOV dul,#5Bh
MOV wel,#80h
ACALL music0
last2: cjne a,#00,last
MOV dptr,#dat1
MOV dul,#06h
MOV wel,#80h
ACALL music0
RET
music0:
MOV 20h,#00h ;中断计数单元清0
music1: clr a
MOVC a,@a+dptr ;查表取音阶常数
JZ end0 ;累加器判0看是否是结束符
CJNE a,#0ffh,music5 ;是休止符?
LJMP music3 ;产生100ms停顿
music5:
NOP
key:
JNB play,k0 ;判断P3.0键是否按下
JNB addone,k1 ;判断P3.2键是否按下
JNB subone,k2 ;判断P3.1键是否按下
MOV r6,a ;音阶常数送R6
INC dptr ;DPTR+1
MOV a,#0
MOVC a,@a+dptr ;取常数送R7
MOV r7,a
SETB tr0 ;启动定时器T0
music2: nop
CJNE r0,#0,$
CPL song ;输出电平取反
MOV a, r6
MOV r3,a ;音阶常数送R3
LCALL del20
MOV a, r7 ;节拍常数送A
CJNE a,20h,music2 ;节拍时间到否
MOV 20h,#00h ;为取下一音阶作准备
INC DPTR
LJMP music1
music3:
NOP ;休止100ms
CLR tr0 ;关闭定时器
MOV r2, #14h
music4: NOP
MOV r3, #250 ;R3=250
LCALL del20
DJNZ r2, music4
INC dptr ;为取下一音阶作准备
LJMP music1
end0: MOV r2, #200 ;歌曲结束后,延时1s后继续
music6: MOV r3, #250
LCALL del20
DJNZ r2,music6
(按键选择)
k1: ACALL del20 ;调用延时子程序
JNB addone,k1 ;判断P3.2键是否释放
ACALL next
k2: ACALL del20
JNB subone,k2 ;判断P3.1键是否释放
ACALL last
k0: ACALL del20
JNB play,k0 ;判断3.0键是否释放
LJMP start
RET
del20: MOV r4,#05h ;延时子程序
del4: NOP
DJNZ r4,del4
DJNZ r3,del20
RET
cont: INC 20h ;计数单元+1
MOV th0,#0dbh ;重新10ms定时初值
MOV tl0,#0ffh
RETI ;跳出中断
(停止播放)
pause: ACALL del20
JNB p3.0,pause ;判断P3.0键是否有释放
MOV a,r0 ;把R0的值给A
CPL a ;A值取反
MOV r0,a
RETI
dat1:
db 3bh,20h,3bh,20h,30h,20h,33h,20h,3bh,80h,0ffh
db 3bh,20h,3bh,20h,26h,20h,2bh,20h,26h,80h,0ffh
db 26h,20h,26h,20h,20h,20h,26h,20h,2bh,20h,2bh,20h,30h,20h,33h,10h,33h,10h
db 3bh,60h,40h,20h,4ch,80h,0ffh
db 3bh,20h,3bh,20h,30h,20h,33h,20h,3bh,80h,0ffh
db 3bh,20h,3bh,20h,26h,20h,2bh,20h,26h,80h,0ffh
db 26h,20h,26h,20h,20h,20h,26h,20h,2bh,20h,2bh,20h,2bh,20h,30h,20h
db 33h,20h,3bh,20h,3bh,20h,40h,2bh,3bh,80h,0ffh
db 19h,20h,1ch,40h,26h,20h,19h,20h,1ch,40h,26h,20h,0ffh
db 20h,20h,1ch,20h,1ch,20h,20h,20h,26h,80h,0ffh
db 19h,20h,1ch,40h,26h,20h,19h,20h,1ch,40h,26h,20h,0ffh
db 20h,20h,1ch,20h,1ch,20h,20h,20h,26h,80h,0ffh
db 2bh,20h,2bh,40h,3bh,20h,2bh,20h,2bh,40h,2bh,20h,0ffh
db 26h,20h,2bh,20h,2bh,20h,30h,20h,2bh,80h,0ffh
db 2bh,20h,2bh,40h,3bh,20h,30h,20h,30h,40h,2bh,20h,0ffh
db 33h,20h,3bh,20h,3bh,20h,40h,20h,3bh,80h,0ffh,0ffh
dat2:
db 18h,30h,1ch,10h,20h,40h,1ch,10h
db 18h,10h,20h,10h,1ch,10h,18h,40h
db 1ch,20h,20h,20h,1ch,20h,18h,20h
db 20h,80h,0ffh,20h,30h,1ch,10h,18h
db 20h,15h,20h,1ch,20h,20h,20h,26h
db 40h,20h,20h,2bh,20h,26h,20h,20h
db 20h,30h,80h,0ffh,20h,20h,1ch,10h
db 18h,10h,20h,20h,26h,20h,2bh,20h
db 30h,20h,2bh,40h,20h,20h,1ch,10h
db 18h,10h,20h,20h,26h,20h,2bh,20h
db 30h,20h,2bh,40h,20h,30h,1ch,10h
db 18h,20h,15h,20h,1ch,20h,20h,20h
db 26h,40h,20h,20h,2bh,20h,26h,20h
db 20h,20h,30h,80h,20h,30h,1ch,10h
db 20h,10h,1ch,10h,20h,20h,26h,20h
db 2bh,20h,30h,20h,2bh,40h,20h,15h
db 1fh,05h,20h,10h,1ch,10h,20h,20h
db 26h,20h,2bh,20h,30h,20h,2bh,40h
db 20h,30h,1ch,10h,18h,20h,15h,20h
db 1ch,20h,20h,20h,26h,40h,20h,20h
db 2bh,20h,26h,20h,20h,20h,30h,30h
db 20h,30h,1ch,10h,18h,40h,1ch,20h
db 20h,20h,26h,40h,13h,60h,18h,20h
db 15h,40h,13h,40h,18h,80h,00h
dat3:
db 26h,20h,20h,20h,20h,20h,26h,10h,20h,10h,20h,80h,26h,20h,30h,20h
db 30h,20h,39h,10h,30h,10h,30h,80h,26h,20h,20h,20h,20h,20h,1ch,20h
db 20h,80h,2bh,20h,26h,20h,20h,20h,2bh,10h,26h,10h,2bh,80h,26h,20h
db 30h,20h,30h,20h,39h,10h,26h,10h,26h,60h,40h,10h,39h,10h,26h,20h
db 30h,20h,30h,20h,39h,10h,26h,10h,26h,80h,26h,20h,2bh,10h,2bh,10h
db 2bh,20h,30h,10h,39h,10h,26h,10h,2bh,10h,2bh,20h,2bh,40h,40h,20h
db 20h,10h,20h,10h,2bh,10h,26h,30h,30h,80h,18h,20h,18h,20h,26h,20h
db 20h,20h,20h,40h,26h,20h,2bh,20h,30h,20h,30h,20h,1ch,20h,20h,20h
db 20h,80h,1ch,20h,1ch,20h,1ch,20h,30h,20h,30h,60h,39h,10h,30h,10h
db 20h,20h,2bh,10h,26h,10h,2bh,10h,26h,10h,26h,10h,2bh,10h,2bh,80h
db 18h,20h,18h,20h,26h,20h,20h,20h,20h,60h,26h,10h,2bh,20h,30h,20h
db 30h,20h,1ch,20h,20h,20h,20h,80h,26h,20h,30h,10h,30h,10h,30h,20h
db 39h,20h,26h,10h,2bh,10h,2bh,20h,2bh,40h,40h,10h,40h,10h,20h,10h
db 20h,10h,2bh,10h,26h,30h,30h,80h,00h
END
复制代码
作者:
279592094
时间:
2017-12-14 20:30
/************************************************************************
[文件名] C51音乐程序(八月桂花)
[功能] 通过单片机演奏音乐
/**********************************************************************/
#include <REG52.H>
#include <INTRINS.H>
//本例采用89C52, 晶振为12MHZ
//关于如何编制音乐代码, 其实十分简单,各位可以看以下代码.
//频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍;
//所以拿出谱子, 试探编吧!
sbit Beep = P2^1 ;
unsigned char n=0; //n为节拍常数变量
unsigned char code music_tab[] ={
0x18, 0x30, 0x1C , 0x10, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数,
0x20, 0x40, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x10,
0x1C, 0x10, 0x18 , 0x40,
0x1C, 0x20, 0x20 , 0x20,
0x1C, 0x20, 0x18 , 0x20,
0x20, 0x80, 0xFF , 0x20,
0x30, 0x1C, 0x10 , 0x18,
0x20, 0x15, 0x20 , 0x1C,
0x20, 0x20, 0x20 , 0x26,
0x40, 0x20, 0x20 , 0x2B,
0x20, 0x26, 0x20 , 0x20,
0x20, 0x30, 0x80 , 0xFF,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,
0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x80,
0x20, 0x30, 0x1C , 0x10,
0x20, 0x10, 0x1C , 0x10,
0x20, 0x20, 0x26 , 0x20,
0x2B, 0x20, 0x30 , 0x20,
0x2B, 0x40, 0x20 , 0x15,
0x1F, 0x05, 0x20 , 0x10,
0x1C, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,
0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x30,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x40, 0x1C , 0x20,
0x20, 0x20, 0x26 , 0x40,
0x13, 0x60, 0x18 , 0x20,
0x15, 0x40, 0x13 , 0x40,
0x18, 0x80, 0x00
};
void int0() interrupt 1 //采用中断0 控制节拍
{ TH0=0xd8;
TL0=0xef;
n--;
}
void delay (unsigned char m) //控制频率延时
{
unsigned i=3*m;
while(--i);
}
void delayms(unsigned char a) //豪秒延时子程序
{
while(--a); //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!
}
void main()
{ unsigned char p,m; //m为频率常数变量
unsigned char i=0;
TMOD&=0x0f;
TMOD|=0x01;
TH0=0xd8;TL0=0xef;
IE=0x82;
play:
while(1)
{
a: p=music_tab[i];
if(p==0x00) { i=0, delayms(1000); goto play;} //如果碰到结束符,延时1秒,回到开始再来一遍
else if(p==0xff) { i=i+1;delayms(100),TR0=0; goto a;} //若碰到休止符,延时100ms,继续取下一音符
else {m=music_tab[i++], n=music_tab[i++];} //取频率常数 和 节拍常数
TR0=1; //开定时器1
while(n!=0) Beep=~Beep,delay(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
TR0=0; //关定时器1
}
}
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1