自制音乐芯片

乐谱输入程序,硬件很简单。

#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)

{

玩(仙剑);

}

}