一、乐理基础
我们可以想办法让我们的蜂鸣器播放一首《故乡的原风景》
首先,《故乡的原风景》是F调的,每小节四拍,以四分音符为1拍
F调:F调就是以C调里面的F为跟音,也就是C调中音里面的第四个音fa,根据乐理知识我们可以计算得到F调的低音、中音和高音部分的半周期:
通过这个图可以计算得到F调的各个音符频率:
唱名 | C | D | E | F | G | A | B |
---|---|---|---|---|---|---|---|
半周期/us | 716 | 638 | 568 | 536 | 478 | 425 | 379 |
二、程序实现
1、存储简谱信息:存储音符的半周期和简谱
uint reset[16]={0, 1432, 1275, 1136, 1072, 955, 851, 758,
716, 638, 568, 536, 478, 425, 379, 358}; //音符半周期
xdata uchar music[42]={ 5,2, 6,2, 8,2, 9,10, 10,1, 9,1, 8,4, 6,1, 10,12,
5,2, 6,2, 8,2, 9,10, 10,1, 9,1, 8,4, 12,8, 10,6, 0,4,
5,2, 6,1, 1,1, 2,12, 3,1, 2,1, 1,4, 6,1, 3,12, 5,2, 6,2, 1,2, 2,14
}; //由音符和时值构成的数组
2、相关变量定义及初始化:设置推挽输出、定时器和中断
#define uchar unsigned char
#define uint unsigned int
uint j=0;
sbit beep=P3^4; //蜂鸣器引脚
void init()
{
P3M0=0x10; //设置推挽输出
P3M1=0x00;
EA=1; //开启总中断
ET0=1;
TR0=1;
beep=0;
}
3、设置时间:定义中断函数、延时函数
void timer0() interrupt 1 //中断函数
{
beep=~beep;
}
void delay(uint t) //延时函数
{
uint z;
for(;t>0;t--)
for(z=800;z>0;z--)
;
}
3、播放音乐:在主函数中调用play函数
void play()
{
if(reset[music[j]]!=0) //若读取到非0的音符则播放
{
TR0=1;
TH0=(65536-reset[music[j]])/256;
TL0=(65536-reset[music[j]])%256;
}
else TR0=0;
delay(250*music[++j]); //设置音符播放时间
TR0=0;
delay(2*music[j]); //播放完一个音停一下
j++;
if(j==42) //设置单曲循环
{j=0;delay(5000);}
}
main()
{
init();
while(1)
play();
}
通过以上程序就可以播放《故乡的原风景》了
第八篇学习笔记完结 cheers !