Ⅰ 单片机 音乐程序编写 歌曲《小星星》
只有音乐发声汇编程序,没有加入LED灯,供参考。数据代码已改为小星星发声
;**********************************************
ORG
0000H
SJMP
MAIN
ORG
0BH
AJMP
TIME0
;*************主程序************************
MAIN:
MOV
SP,#60
MOV
TMOD,#01H
;T0定时工作方式
MOV
IE,#82H
;CPU
中断允许,T0中断允许
START0:
MOV
30H,#00H
;TABLE
相对地址指针
NEXT:
MOV
A,30H
MOV
DPTR,#TABLE
;到TABLE处取
简谱码
节拍
码
MOVC
A,@A+DPTR
MOV
R2,A
;取到的简谱码
节拍码
暂存于R2中
JZ
ENDF
;取到
00
结束
ANL
A,#0FH
;否,取低四位
节拍
码
MOV
R5,A
;将节拍码存于R5中
MOV
A,R2
;简谱码
节拍
码
给A
SWAP
A
;高4位
与
低4位
交换
ANL
A,#0FH
;取简谱
码
JNZ
SING
;取到的简谱
码不是0,则去发声
CLR
TR0
;取到0
则不发声
SJMP
DLY1
;节拍延时子程序(
随节拍码变化,延时时间不同)
;---------------发声-----------------------
SING:
DEC
A
;取到的简谱码减1
;(简谱码计数值16位数据存储首地址从TABLE1
《相对地址》0处开始放起,所以要减1)
MOV
22H,A
;存入(22H)中
RL
A
;乘2
因为取的数据占两字节(16位)
;所以指针增加量要乘2
MOV
DPTR,#TABLE1
;...........简谱码转换为相应定时器16位计数值.............
MOVC
A,@A+DPTR
;到TABLE1取相应的高字节计数值
MOV
TH0,A
;高字节计数值存入TH0和(21H)中
MOV
21H,A
MOV
A,22H
;减1的简谱码给A
RL
A
;乘2
因为取的数据占两字节(16位)
;所以指针增加量要乘2
INC
A
;A
增加
取下一个字节计数值
;...........简谱码转换为相应定时器16位计数值.............
MOVC
A,@A+DPTR
;到TABLE1取相应的低字节计数值
MOV
TL0,A
;低字节计数值存入TL0和(20H)中
MOV
20H,A
SETB
TR0
;启动T0定时器让喇叭发出不同频率声音
;---------------节拍延时-------------------
DLY1:
ACALL
DELAY
;基本单位时间为1/4拍
187ms
INC
30H
;取下一个简谱码
节拍
码
SJMP
NEXT
;---------------歌放完结束---------------
ENDF:
CLR
TR0
;关闭T0定时器
AJMP
START0
;反复循环
;****T0中断子程序(用来驱动喇叭发出不同频率声音)**************
TIME0:
PUSH
ACC
PUSH
PSW
MOV
TL0,20H
;重装计数值
MOV
TH0,21H
CPL
P3.7
;驱动发声
POP
PSW
POP
ACC
RETI
;******************节拍延时187ms****************************
DELAY:
MOV
R7,#187
;187ms延时子程序
DLY2:
MOV
R4,#02
DLY3:
MOV
R3,#248
DJNZ
R3,$
DJNZ
R4,DLY3
DJNZ
R7,DLY2
DJNZ
R5,DELAY
RET
;*******音符T值表(用来让定时器发出不同的频率)**DW
表示一个
计数值
占两个字节存储单元***************
TABLE1:
DW
64260,64400,64524,64580,64684
;低音SO
低音LA
低音SI
/中音DO
中音RE
DW
64777,64820,64898,64968,65030
;中音MI
中音FA
中音SO
中音LA
中音SI
DW
65058,65110,65157,65178,65217
;高音DO
高音RE
高音MI
高音FA
高音SO
;*********简谱码
节拍码(高4位简谱码
,低4位节拍码)*************
TABLE:
DB
44H,44H,84H,84H
;
1
1
5
5
DB
094H,094H,88h
;
6
6
5
-
DB
74H,74H,63H,63H;
4
4
3
3
DB
52H,52H,48h
;
2
2
1-
DB
84H,84H,74H,74H
;
5
5
4
4
DB
64H,64H,58h;
3
3
2-
DB
84H,84H,74H,74H
;
5
5
4
4
DB
64H,64H,58h
;
3
3
2-
DB
44H,44H,84H,84H
;
1
1
5
5
DB
094H,094H,88h;
6
6
5
-
DB
74H,74H,63H,63H;
4
4
3
3
DB
52H,52H,48h;
2
2
1-
END
加入了LED灯,水平有限,效果有点不太好
;**********************************************
ORG
0000H
SJMP
MAIN
ORG
0BH
AJMP
TIME0
;*************主程序************************
MAIN:
MOV
SP,#60
MOV
TMOD,#01H
;TO定时工作方式
MOV
IE,#82H
;CPU
中断允许,TO中断允许
START0:
MOV
30H,#00H
;TABLE
相对地址指针
NEXT:
MOV
A,30H
MOV
DPTR,#TABLE
;到TABLE处取
简谱码
节拍
码
MOVC
A,@A+DPTR
MOV
R2,A
;取到的简谱码
节拍码
暂存于R2中
JZ
ENDF
;取到
00
结束
ANL
A,#0FH
;否,取低四位
节拍
码
MOV
R5,A
;将节拍码存于R5中
MOV
A,R2
;简谱码
节拍
码
给A
SWAP
A
;高4位
与
低4位
交换
ANL
A,#0FH
;取简谱
码
JNZ
SING
;取到的简谱
码不是0,则去发声
CLR
TR0
;取到0
则不发声
SJMP
DLY1
;节拍延时子程序(
随节拍码变化,延时时间不同)
;---------------发声-----------------------
SING:
DEC
A
;取到的简谱码减1
;(简谱码计数值16位数据存储首地址从TABLE1
《相对地址》0处开始放起,所以要减1)
MOV
22H,A
;存入(22H)中
RL
A
;乘2
因为取的数据占两字节(16位)
;所以指针增加量要乘2
MOV
DPTR,#TABLE1
;...........简谱码转换为相应定时器16位计数值.............
MOVC
A,@A+DPTR
;到TABLE1取相应的高字节计数值
MOV
TH0,A
;高字节计数值存入TH0和(21H)中
MOV
21H,A
MOV
A,22H
;减1的简谱码给A
RL
A
;乘2
因为取的数据占两字节(16位)
;所以指针增加量要乘2
INC
A
;A
增加
取下一个字节计数值
;...........简谱码转换为相应定时器16位计数值.............
MOVC
A,@A+DPTR
;到TABLE1取相应的低字节计数值
MOV
TL0,A
;低字节计数值存入TL0和(20H)中
MOV
20H,A
SETB
TR0
;启动T0定时器让喇叭发出不同频率声音
;---------------节拍延时-------------------
DLY1:
ACALL
DELAY
;基本单位时间为1/4拍
187ms
INC
30H
;取下一个简谱码
节拍
码
CPL
P1.0
LED灯
闪烁
CPL
P1.1
CPL
P1.2
CPL
P1.3
CPL
P1.4
CPL
P1.5
CPL
P1.6
CPL
P1.7
SJMP
NEXT
;---------------歌放完结束---------------
ENDF:
CLR
TR0
;关闭T0定时器
AJMP
START0
;反复循环
;****T0中断子程序(用来驱动喇叭发出不同频率声音)**************
TIME0:
PUSH
ACC
PUSH
PSW
MOV
TL0,20H
;重装计数值
MOV
TH0,21H
CPL
P3.7
;驱动发声
POP
PSW
POP
ACC
RETI
;******************节拍延时187ms****************************
DELAY:
MOV
R7,#187
;187ms延时子程序
DLY2:
MOV
R4,#02
DLY3:
MOV
R3,#248
DJNZ
R3,$
DJNZ
R4,DLY3
DJNZ
R7,DLY2
DJNZ
R5,DELAY
RET
;*******音符T值表(用来让定时器发出不同的频率)**DW
表示一个
计数值
占两个字节存储单元***************
TABLE1:
DW
64260,64400,64524,64580,64684
;低音SO
低音LA
低音SI
/中音DO
中音RE
DW
64777,64820,64898,64968,65030
;中音MI
中音FA
中音SO
中音LA
中音SI
DW
65058,65110,65157,65178,65217
;高音DO
高音RE
高音MI
高音FA
高音SO
;*********简谱码
节拍码(高位简谱码
,低位节拍码)*************
TABLE:
DB
44H,44H,84H,84H
;
1
1
5
5
DB
094H,094H,88h
;
6
6
5
--表示有节拍
DB
74H,74H,63H,63H
;
4
4
3
3
DB
52H,52H,48h
;
2
2
1-
DB
84H,84H,74H,74H
;
5
5
4
4
DB
64H,64H,58h
;
3
3
2-
DB
84H,84H,74H,74H
;
5
5
4
4
DB
64H,64H,58h
;
3
3
2-
DB
44H,44H,84H,84H
;
1
1
5
5
DB
094H,094H,88h
;
6
6
5
-
DB
74H,74H,63H,63H
;
4
4
3
3
DB
52H,52H,48h
;
2
2
1-
END
Ⅱ 单片机播放音乐的原理
单片机发音原理:利用定时器或PWM功能,输出PWM,经一级有源滤波后放大驱动扬声器。
单片机演奏音乐基本是单音频率,它不包含相应幅度的谐波频率,
也就是说不能象电子琴那样能奏出多种音色的声音,但一定要弄清楚两个概念即可,也就是“音调”和“节拍” 。音调 表示一个音符唱多高的频率。节拍 表示一个音符唱多长的时间
1.要生产音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间.利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。
2. 利用8051的内部定时器使用其工作在计数器模式MODE1下,改变计数值THO及TLO以产生不同频率的方法。
Ⅲ 这是一个利用89C52RC单片机蜂鸣器演奏生日快乐歌。请高手帮我解释一下:整体思想,再在每一步添加注释。
#include<reg51.h>
sbit speaker=P1^6;
unsigned char timer0h,timer0l,time;
//生日歌,这三个字节一组,分别定义:旋律(1234567)、高低音(低音、中音、高音)、节奏(长度)
code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
// 音阶频率表 高八位,也就是发音对应频率的高八位
code unsigned char FREQH[]={0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,} ;
// 音阶频率表 低八位,也就是发音对应频率的低八位
code unsigned char FREQL[]={0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16, };
void delay(unsigned char t) //延时程序
{
unsigned char t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{ ; } }
TR0=0;
}
void t0int() interrupt 1 //定时器0中断服务程序,控制声音打频率
{ TR0=0;
speaker=!speaker;
TH0=timer0h;
TL0=timer0l;
TR0=1;
}
void song() //启动演奏当前频率
{ TH0=timer0h; //当前频率的高八位
TL0=timer0l; //当前频率的低八位
TR0=1; //启动定时器0
delay(time); //延时当前频率的演奏时间
}
void main(void)
{
unsigned char k,i;
TMOD=1; //置CT0定时工作方式1 EA=1; ET0=1;//IE=0x82 //CPU开中断,CT0开中断
while(1)
{
i=0;
while(i<75)
{ //音乐数组长度 ,唱完从头再来
k=sszymmh[i]+7*sszymmh[i+1]-1; //取当前节奏的频率地址
timer0h=FREQH[k]; //取当前频率高八位
timer0l=FREQL[k]; //取当前频率低八位
time=sszymmh[i+2]; //取当前频率的时长
i=i+3; //三个字节一组
song(); //演奏当前频率,共75/3,25个曲调。
}
}
}
//程序的设计思路就是将一首乐曲分成三个变量来控制,分别是曲调、所在音区、时长。而控制曲调的因素也就是频率又分成高八位和第八位两个表,每演奏一个曲调,就根据该曲调的三个变量来取值。
Ⅳ 让单片机唱歌的c语言程序是怎么弄的
其实原理很简单,就是控制单片机的某个引脚,输出一定频率的方波信号,而输出方波信号的方法,是最基础的,最简单的编程了,用定时器定时,根据信号频率算出信号周期,然后计算出定时的时间。那单片机演奏歌曲的程序,也是同样的原理,只是事先根据歌曲的简谱查出每个音阶的信号频率,再根据各音阶频率计算出定时器的初值。演奏时,按简谱的各音阶顺序输出不同的频率的信号就行了。
下表是音阶与频率对应关系表,给出常用音阶对应的定时常数。
Ⅳ 51单片机唱歌怎么实现啊
单片机可以演奏从低音、中音、高音和超高音,四个八度共28个音符。
演奏乐曲时,就根据音符的不同数值,从半周期数据表中找到定时时间初始值,送入定时器即可控制发音的音调。
比如把表中的0xF2和0x42送到定时器,定时器按照这个初始值来产生中断,输出的方波,人们听起来,这就是低音1。
乐曲的数据,也要写个数据表,程序中以 code unsigned char sszymmh[] 命名。
这个表中每三个数字,说明了一个音符,它们分别代表:
第一个数字是音符的数值1234567之一,代表多来咪发...;
第二个数字是0123之一,代表低音、中音、高音、超高音;
第三个数字是时间长度,以半拍为单位。
乐曲数据表的结尾是三个0。
Ⅵ 用51单片机实现音乐播放的原理是什么
需要写一段程序。
如果是简单的音乐,编乐谱推蜂鸣器就可以;如果是mp3/wav之类的音乐,需要芯片自带解码模块,或者使用外部解码芯片,还需要dac将声音推出来。
声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单处机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的矩形波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调。要准确奏出一首曲子,必须准确地控制乐曲节奏,即一音符的持续时间。音符的节拍我们可以用定时器T0来控制,送入不同的初值,就可以产生不同的定时时间。便如某歌曲的节奏为每分钟94拍,即一拍为0.64秒。
Ⅶ 单片机,用一个蜂鸣器可以演奏出音乐吗
当然可以。
单片机演奏一个音符,是通过引脚,周期性的输出一个特定频率的方波。
这就需要单片机,在半个周期内输出低电平、另外半个周期输出高电平,周而复始。
众所周知,周期为频率的倒数,可以通过音符的频率计算出周期;演奏时,要根据音符的不同,把对应的、半个周期的定时时间初始值,送入定时器,再由定时器按时输出高低电平。
Ⅷ 单片机电子琴演奏
八键电子琴.hex:
:
:
:
:
:
:
:
:
:
:
:03000B000200B739
:0900B70085098C850A8AB2B73272
:030000000200AB50
:
:00000001FF
八键触摸电子琴.hex:
:
:
:
:
:
:
:
:
:
:
:
:03000B000200C52B
:0900C50085098C850A8AB2B73264
:030000000200B942
:
:00000001FF
老鼠爱大米.hex:
:03000000020014E7
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:00000001FF
图太大,告诉我邮箱,我发你。