📄 playsongs.lst
字号:
C51 COMPILER V8.02 PLAYSONGS 11/22/2008 15:15:03 PAGE 1
C51 COMPILER V8.02, COMPILATION OF MODULE PLAYSONGS
OBJECT MODULE PLACED IN PlaySongs.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE PlaySongs.c BROWSE DEBUG OBJECTEXTEND
line level source
1 //51单片机播放音乐库文件
2 /**************************************************************************
3
4 SOUND PLAY FOR 51MCU
5
6 COPYRIGHT (c) 2005 BY JJJ.
7 -- ALL RIGHTS RESERVED --
8
9 File Name: SoundPlay.h
10 Author: Jiang Jian Jun
11 Created: 2005/5/16
12 Modified: NO
13 Revision: 1.0
14
15 *******************************************************************************/
16
17 /*说明**************************************************************************
18 曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)
19
20 音高由三位数字组成:
21 个位是表示 1~7 这七个音符
22 十位是表示音符所在的音区:1-低音,2-中音,3-高音;
23 百位表示这个音符是否要升半音: 0-不升,1-升半音。
24
25 音长最多由三位数字组成:
26 个位表示音符的时值,其对应关系是:
27 |数值(n): |0 |1 |2 |3 | 4 | 5 | 6
28 |几分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n
29 十位表示音符的演奏效果(0-2): 0-普通,1-连音,2-顿音
30 百位是符点位: 0-无符点,1-有符点
31
32 调用演奏子程序的格式
33 Play(乐曲名,调号,升降八度,演奏速度);
34 |乐曲名 : 要播放的乐曲指针,结尾以(0,0)结束;
35 |调号(0-11) : 是指乐曲升多少个半音演奏;
36 |升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;
37 |演奏速度(1-12000): 值越大速度越快;
38
39 ***************************************************************************/
40 #ifndef __SOUNDPLAY_H_REVISION_FIRST__
41 #define __SOUNDPLAY_H_REVISION_FIRST__
42
43 #include <REGX51.H>
44
45 //**************************************************************************
46
47 #define SYSTEM_OSC 11059200//12000000 //定义晶振频率12000000HZ
48 #define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//每4分音符间隔
49 sbit BeepIO = P0^1; //定义输出管脚
50 #define LIGHTS P1
51
52 ////// 指示灯部分 //////
53 extern void LEDShow(unsigned int LEDStatus);
54 void LEDShow(unsigned int LEDStatus)
55 {
C51 COMPILER V8.02 PLAYSONGS 11/22/2008 15:15:03 PAGE 2
56 1 LIGHTS = ~LEDStatus;
57 1 }
58 ////////////////////////
59 unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
60 unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
61 unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };
62 unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
63 unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存
64 //**************************************************************************
65 void InitialSound(void)
66 {
67 1 BeepIO = 1;
68 1 Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; // 计算TL1应装入的初值 (10ms的初装值)
69 1 Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256; // 计算TH1应装入的初值
70 1 TH1 = Sound_Temp_TH1;
71 1 TL1 = Sound_Temp_TL1;
72 1 TMOD |= 0x11;
73 1 ET0 = 1;
74 1 ET1 = 0;
75 1 TR0 = 0;
76 1 TR1 = 0;
77 1 EA = 1;
78 1 }
79
80 void BeepTimer0(void) interrupt 1 //音符发生中断
81 {
82 1 BeepIO = !BeepIO;
83 1 TH0 = Sound_Temp_TH0;
84 1 TL0 = Sound_Temp_TL0;
85 1 }
86 //**************************************************************************
87 void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
88 {
89 1 unsigned int NewFreTab[12]; //新的频率表
90 1 unsigned char i,j;
91 1 unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
92 1 ////// 指示灯部分 //////
93 1 unsigned char LEDFlash, OFFSet;
94 1 ////////////////////////
95 1 unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
96 1 for(i=0;i<12;i++) // 根据调号及升降八度来生成新的频率表
97 1 {
98 2 j = i + Signature;
99 2 if(j > 11)
100 2 {
101 3 j = j-12;
102 3 NewFreTab[i] = FreTab[j]*2;
103 3 }
104 2 else
105 2 NewFreTab[i] = FreTab[j];
106 2
107 2 if(Octachord == 1)
108 2 NewFreTab[i]>>=2;
109 2 else if(Octachord == 3)
110 2 NewFreTab[i]<<=2;
111 2 }
112 1
113 1 SoundLength = 0;
114 1 while(Sound[SoundLength] != 0x00) //计算歌曲长度
115 1 {
116 2 SoundLength+=2;
117 2 }
C51 COMPILER V8.02 PLAYSONGS 11/22/2008 15:15:03 PAGE 3
118 1
119 1 Point = 0;
120 1 Tone = Sound[Point];
121 1 Length = Sound[Point+1]; // 读出第一个音符和它时时值
122 1
123 1 LDiv0 = 12000/Speed; // 算出1分音符的长度(几个10ms)
124 1 LDiv4 = LDiv0/4; // 算出4分音符的长度
125 1 LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准
126 1 TR0 = 0;
127 1 TR1 = 1;
128 1 while(Point < SoundLength)
129 1 {
130 2 SL=Tone%10; //计算出音符
131 2 SM=Tone/10%10; //计算出高低音
132 2 SH=Tone/100; //计算出是否升半
133 2 //// 指示灯部分 /////
134 2 LEDFlash = SM*((SL/2)+1);
135 2 LEDShow(~(0xFE<<LEDFlash));
136 2 //////////////////////////
137 2 CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率
138 2 if(SL!=0)
139 2 {
140 3 if (SM==1) CurrentFre >>= 2; //低音
141 3 if (SM==3) CurrentFre <<= 2; //高音
142 3 Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
143 3 Sound_Temp_TH0 = Temp_T/256;
144 3 Sound_Temp_TL0 = Temp_T%256;
145 3 TH0 = Sound_Temp_TH0;
146 3 TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿
147 3 }
148 2 SLen=LengthTab[Length%10]; //算出是几分音符
149 2 XG=Length/10%10; //算出音符类型(0普通1连音2顿音)
150 2 FD=Length/100;
151 2 LDiv=LDiv0/SLen; //算出连音音符演奏的长度(多少个10ms)
152 2 if (FD==1)
153 2 LDiv=LDiv+LDiv/2;
154 2 if(XG!=1)
155 2 if(XG==0) //算出普通音符的演奏长度
156 2 if (SLen<=4)
157 2 LDiv1=LDiv-LDiv4;
158 2 else
159 2 LDiv1=LDiv*SOUND_SPACE;
160 2 else
161 2 LDiv1=LDiv/2; //算出顿音的演奏长度
162 2 else
163 2 LDiv1=LDiv;
164 2 if(SL==0) LDiv1=0;
165 2 LDiv2=LDiv-LDiv1; //算出不发音的长度
166 2 if (SL!=0)
167 2 {
168 3 TR0=1;
169 3 for(i=LDiv1;i>0;i--) //发规定长度的音
170 3 {
171 4 //// 指示灯部分 ////
172 4 OFFSet = (OFFSet+1)%5;
173 4 LEDShow(~(0xFE<<(LEDFlash+OFFSet-2)));
174 4 /////////////////////
175 4 while(TF1==0);
176 4 TH1 = Sound_Temp_TH1;
177 4 TL1 = Sound_Temp_TL1;
178 4 TF1=0;
179 4 }
C51 COMPILER V8.02 PLAYSONGS 11/22/2008 15:15:03 PAGE 4
180 3 }
181 2 if(LDiv2!=0)
182 2 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -