📄 play.lst
字号:
C51 COMPILER V7.20 PLAY 11/20/2004 22:27:59 PAGE 1
C51 COMPILER V7.20, COMPILATION OF MODULE PLAY
OBJECT MODULE PLACED IN play.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE play.c BROWSE DEBUG OBJECTEXTEND
line level source
1 /* 51单片机演奏音乐子程序 play.c*/
2 /* 本程序用T0来产生音调,用T1产生音长 */
3 #include<reg51.h>
4 #define yx 4/5 /* 定义普通音符演奏的长度分率 */
5 #define plen 2 /* 定义晶振的时钟周期(us) */
6 #define uchar unsigned char
7 #define uint unsigned int
8 sbit speaker=P3^5;
9 uchar tc0,tc1,sc0,sc1; /* 音长和音符两个计数器初值暂存 */
10 void play(sound,dh,sj,speed,point1,point2)
11 uchar code sound[]; /* 接受乐曲数组的地址 */
*** WARNING C258 IN LINE 11 OF PLAY.C: 'sound': mspace on parameter ignored
12 uchar speed,sj,dh; /* 速度、八度、调号 */
13 uint point1,point2; /* 乐曲开始、结束指针 */
14 {
15 1 uint code fftab[12]={262,277,294,311,330,349,369,392,415,440,466,494}; /* 频率表*/
16 1 uchar code stab[7]={0,2,4,5,7,9,11}; /* 1~7在频率表中的位置 */
17 1 uchar code ltab[7]={1,2,4,8,16,32,64};
18 1 uchar tl,ts,sl,sm,sh,slen,xg,ii,fd;
19 1 uint point,hz,tc,sc,len,len0,len1,len2,len4,i,ftab[12];
20 1 speaker=1;
21 1 for(i=0;i<12;i++) /* 根据调号及升降八度来计算音符频率 */
22 1 {
23 2 ii=i+dh;
24 2 if(ii>11)
25 2 {
26 3 ii=ii-12;
27 3 ftab[i]=fftab[ii]*2;
28 3 }
29 2 else
30 2 ftab[i]=fftab[ii];
31 2 if(sj==1) ftab[i]>>=2;
32 2 if(sj==3) ftab[i]<<=2;
33 2 }
34 1 point=point1;
35 1 ts=sound[point];
36 1 tl=sound[point+1]; /* 读出第一个音符和它时时值 */
37 1 tc=65535-10000/plen; /* 算出10ms的初装值 */
38 1 tc0=tc%256; /* 计算TL1应装入的初值 */
39 1 tc1=tc/256; /* 计算TH1应装入的初值 */
40 1 len0=12000/speed; /* 算出1分音符的长度(几个10ms) */
41 1 len4=len0/4; /* 算出4分音符的长度 */
42 1 len4=len4-len4*yx; /* 普通音最长间隔标准 */
43 1 TMOD=0x11;
44 1 TH1=tc1; TL1=tc0;
45 1 ET0=1; EA=1;
46 1 TR0=0; TR1=1;
47 1 while(point<=point2)
48 1 {
49 2 sl=ts%10; /* 计算出音符 */
50 2 sh=ts/100; /* 计算出是否升半 */
51 2 sm=ts/10%10; /* 计算出高低音 */
52 2 hz=ftab[stab[sl-1]+sh]; /* 查出对应音符的频率 */
53 2 if(sl!=0)
54 2 {
C51 COMPILER V7.20 PLAY 11/20/2004 22:27:59 PAGE 2
55 3 if (sm==1) hz>>=2; /* 若是低音 */
56 3 if (sm==3) hz<<=2; /* 若是高音 */
57 3 sc=(50000/hz)*10/plen; /* 计算脉冲个数 */
58 3 sc=65536-sc; /* 计算计数器初值 */
59 3 sc0=sc%256; /* 算出TL0应装初值 */
60 3 sc1=sc/256; /* 算出TH0应装初值 */
61 3 TH0=sc1; /* 装入初值 */
62 3 TL0=sc0+12; /* 加12是对中断延时的补偿 */
63 3 }
64 2 slen=ltab[tl%10]; /* 算出是几分音符 */
65 2 xg=tl/10%10; /* 算出音符类型(0普通1连音2顿音) */
66 2 fd=tl/100;
67 2 len=len0/slen; /* 算出连音音符演奏的长度(多少个10ms)*/
68 2 if (fd==1) len=len+len/2;
69 2 if(xg!=1)
70 2 if(xg==0) /* 算出普通音符的演奏长度 */
71 2 if (slen<=4)
72 2 len1=len-len4;
73 2 else
74 2 len1=len*yx;
75 2 else
76 2 len1=len/2; /* 算出顿音的演奏长度 */
77 2 else
78 2 len1=len;
79 2 if(sl==0) len1=0;
80 2 len2=len-len1; /* 算出不发音的长度 */
81 2 if (sl!=0)
82 2 {
83 3 TR0=1;
84 3 for(i=len1;i>0;i--) /* 发规定长度的音 */
85 3 {
86 4 while(TF1==0);
87 4 TH1=tc1; TL1=tc0;
88 4 TF1=0;
89 4 }
90 3 }
91 2 if(len2!=0)
92 2 {
93 3 TR0=0; speaker=1;
94 3 for(i=len2;i>0;i--) /* 音符间的间隔 */
95 3 {
96 4 while(TF1==0);
97 4 TH1=tc1; TL1=tc0;
98 4 TF1=0;
99 4 }
100 3 }
101 2 point+=2; /* 音符指针下移 */
102 2 ts=sound[point]; tl=sound[point+1]; /* 读出下一个音符和它时时值 */
103 2 }
104 1 }
105 void yin() interrupt 1 /* 音符发生程序(中断服务程序)*/
106 {
107 1 speaker=~speaker;
108 1 TH0=sc1; TL0=sc0;
109 1 }
110
111
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 739 ----
CONSTANT SIZE = 38 ----
C51 COMPILER V7.20 PLAY 11/20/2004 22:27:59 PAGE 3
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 4 52
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 1 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -