自制音乐芯片
#define uchar unsigned char //定义它是为了方便使用。
#定义uint无符号整数
#定义ulong无符号长整型
# include & ltreg52.h & gt//包含带有52标准内核的头文件。
字符代码dx 516[3]_ at _ 0x 003 b;//这是为模拟而设置的。
sbit beep=p1^7;//喇叭输出引脚
sbit k 1 = p3^2;
sbit k2 = p3^5;
sbit k3 = p2^4;
sbit k4 = p2^5;
uchar th0 _ f;//中断中加载的T0值高8位。
uchar tl0 _ f;//中断中加载的T0值低8位。
//T0的值和输出频率对照表。
uchar代码频率[36*2]={
0xA9,0xEF,//00220HZ,1 //0
0x93,0xF0,//00233HZ,1#
0x73,0xF1,//00247HZ,2
0x49,0xF2,//00262HZ,2#
0x07,0xF3,//00277HZ,3
0xC8,0xF3,//00294HZ,4
0x73,0xF4,//00311HZ,4#
0x1E,0xF5,//00330HZ,5
0xB6,0xF5,//00349HZ,5#
0x4C,0xF6,//00370HZ,6
0xD7,0xF6,//00392HZ,6#
0x5A,0xF7,//00415HZ,7
0xD8,0xF7,//00440HZ 1 //12
0x4D,0xF8,//00466HZ 1# //13
0xBD,0xF8,//00494HZ 2 //14
0x24,0xF9,//00523HZ 2# //15
0x87,0xF9,//00554HZ 3 //16
0xE4,0xF9,//00587HZ 4 //17
0x3D,0xFA,//00622HZ 4# //18
0x90,0xFA,//00659HZ 5 //19
0xDE,0xFA,//00698HZ 5# //20
0x29,0xFB,//00740HZ 6 //21
0x6F,0xFB,//00784HZ 6# //22
0xB1,0xFB,//00831HZ 7 //23
0xEF,0xFB,//00880HZ `1
0x2A,0xFC,//00932HZ `1#
0x62,0xFC,//00988HZ `2
0x95,0xFC,//01046HZ `2#
0xC7,0xFC,//01109HZ `3
0xF6,0xFC,//01175HZ `4
0x22,0xFD,//01244HZ `4#
0x4B,0xFD,//01318HZ `5
0x73,0xFD,//01397HZ `5#
0x98,0xFD,//01480HZ `6
0xBB,0xFD,//01568HZ `6#
0xDC,0xFD,//01661HZ `7 //35
};
//定时中断0用于产生歌唱频率。
定时器0()中断1
{
TL0 = TL0 _ f;TH0 = TH0 _ f;//调入预设的时间值
哔= ~哔;//反转音乐输出IO
}
//******************************
//乐谱字符串解释函数
//Entry:要解释的乐谱字符串、音调字符串输出、持续时间字符串输出。
changedata(乌恰*宋,乌恰*刁,乌恰*杰)
{
uchar i,i1,j;
夏尔·高第;//高低+/-12刻度
乌恰尔班银;//有半尖音阶吗?
乌查尔·尹畅;//声音长度
uchar代码Jie 7[8]=;//C键的7个值
*刁= *宋;
for(i=0,I 1 = 0;;)
{
高第= 0;//高度=0
半阴= 0;//半音=0
尹畅= 4;//音长1拍
if((*(song+I)= = ' | ')| |(*(song+I)= ' '))i++;
//节拍间隔和空间过滤器
开关(*(宋+我))
{
案例',':高第=-12;i++;//低音
打破;
案例'`':高第= 12;i++;//高音
打破;
}
If(*(song+i)==0) //遇到0时结束。
{
*(Diao+I 1)= 0;//添加结束标志0
*(杰+I 1)= 0;
返回;
}
j=*(宋+我)-0x 30;i++;//取出参考音
j = Jie 7[j]+高第;//添加高音和低音音符
yinc: switch(*(song+i))
{
大小写' #': //有一个半音J加一个音阶。
i++;j++;
goto yinc
大小写'-': //一个音节拉长。
尹畅+= 4;
i++;
goto yinc
大小写' _': //缩短一个音节。
尹畅/= 2;
i++;
goto yinc
案例“.”://有一加半拍。
尹畅=尹畅+尹畅/2;
i++;
goto yinc
}
*(Diao+I 1)= j;//记录笔记
*(杰+I 1)=尹畅;//记录声音长度
I 1++;
}
}
//******************************************
//播放功能
//入口:要播放的乐谱字符串。
无效播放(uchar *songdata)
{
uchar i,c,j = 0;
uint n;
uchar xdata diaodata[112];//音调缓冲
uchar xdata Jie data[112];//声音长度缓冲区
changedata(songdata,diaodata,Jie data);//解释乐谱字符串。
TR0 = 1;
for(I = 0;diodata[I]!=0;I++) //逐符号播放。
{
tl0 _ f = freq[Diao data[I]* 2];//取出相应的计时值,发送给T0。
th0 _ f = freq[Diao data[I]* 2+1];
for(c = 0;c & ltJie data[I];C++) //根据声音长度延迟
for(n = 0;n & lt32000;n++);
TR0 = 0;
for(n = 0;n & lt500;n++);//音符之间的时间延迟
TR0 = 1;
}
TR0 = 0;
}
//仙剑
uchar代码仙剑[]={
"|3_3_3_2_3-|2_3_2_2_,6,6_,7_|12_1_,7,6_,5_|,6 - |"
"3_3_3_2_3.6_|5_6_5_5_22_3_|45_4_32_1_|3.- 3_|"
"67_6_55_3_|5 - 3_5_|26_5_32_3_|3 - |"
"26_6_6-|16_6_66_7_|`17_6_76_7_|3.- 3_|"
"67_6_55_3_|5 - 3_5_|67_6_76_7_|3 - |"
"26_6_6-|16_6_66_7_|`17_6_7.5_|6 - |"
};
//乐谱输入方式播放的音乐,仙剑奇侠传。
Void main(void) //主程序
{
TMOD = 0x 01;//使用定时器0的16位工作模式。
TR0 = 0;
ET0 = 1;
EA = 1;
while(1)
{
玩(仙剑);
}
}