📄 music.c
字号:
#include <reg52.h>
#include <ctype.h>
sbit spk=P1^3;
//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------
#define uint unsigned int
#define uchar unsigned char
#define OSFREQ 6000000l /*所使用的晶振频率*/ /*所使用的晶振频率*/
/**************音符频率表****************/
uint code notefreq[]={ 523, 587, 659, 698, 784, 880, 988,
1047,1175,1319,1396,1568,1760,1976,
2093,2349,2637,2793,3136,3520,3961};
//uint code timreg[]={ 65058, 65110, 65157, 65178, 65217, 65252, 65283,
// 65297,65323,65347,65357,65377,65394,65410,
// 65417,65430,65441,65447,65456,65465,65473};
/*************音名***************/
uchar code notename[]={ 'c','d','e','f','g','a','b',
'1','2','3','4','5','6','7',
'C','D','E','F','G','A','B',0};
/*************半音频率表*****************/
uint code halfnotefreq[]={ 554, 622, 740, 831, 933,
1109,1245,1480,1161,1865,
2218,2489,2960,3322,3729};
//uint code halftimreg[]={ 65085, 65134, 65198, 65235, 65268,
// 65311,65335,65367,65321,65402,
// 65423,65436,65452,65461,65469};
/*************音名***************/
uchar code halfnotename[]={ 'c','d','f','g','a',
'1','2','4','5','6',
'C','D','F','G','A',0};
//sbit BEEP_PWR=P1^0;
uchar FreqSandH,FreqSandL; /*产生方波的定时器的初值*/
uchar timer1cnt; /*定时器延时计数 */
uchar timer1cntflg; /*定时器定时完成标志 */
/***************************************************************************************
函数名称: void timer0int() interrupt 1
功能描述: 定时器0中断用来产生方波
输入: 无
输出: 无
全局变量: TH0,TL0,P5
调用模块: 无
***************************************************************************************/
void timer0int () interrupt 3
{
TH1=FreqSandH;
TL1=FreqSandL;
spk^=1; // change state of P5.4
}
/*void delay1(unsigned char ms)
{
unsigned char j;
while(ms--)
{
for(j=0;j<120;j++);
}
}
/***************************************************************************************
函数名称: void delay(uchar time)
功能描述: 延时
输入: uchar time: 延时时间长度
输出: 无
全局变量: 无
调用模块: 无
***************************************************************************************/
void delay2(uchar time)
{
uchar i;
uint j;
for(i=0;i<time;i++)
for(j=0;j<0x900;j++);
}
/***************************************************************************************
函数名称: void sound(uint freq)
功能描述:
输入: uint freq: 频率值
输出: 无
全局变量: OSFFEQ,FreqSandH,FreqSandL,TR0,ET0
调用模块: 无
***************************************************************************************/
void Sound(uint freq)
{
uint timreg;
timreg=65536l-(OSFREQ/(24l*freq));
FreqSandH=timreg/256;
FreqSandL=timreg&0x00ff;
TR1=1;
ET1=1;
}
/***************************************************************************************
函数名称: void Soundoff(void)
功能描述: 停止发声
输入: 无
输出: 无
全局变量: TR0,ET0,P5
调用模块: 无
***************************************************************************************/
void SoundOff(void)
{
TR1=0;
ET1=0;
//P5 = P5 & 0xef;
spk =1;
}
/***************************************************************************************
函数名称: void GetFreq(uchar ch, uchar flag)
功能描述: 依据音名取对应的频率
输入: uchar ch: 音名
uchar flg: 全音/半音选择
输出: 返回频率值
全局变量: halfnotename[],notename[],halfnotefreq[],notefreq[]
调用模块: 无
***************************************************************************************/
uint GetFreq(uchar ch,uchar flg)
{
uchar * pn,i=0;
uint * pf;
if(flg) {pn=halfnotename; pf=halfnotefreq;}
else {pn=notename; pf=notefreq;}
while(1)
{
if(pn[i]==0) return 0;
if(ch==pn[i]) return pf[i];
i++;
}
}
/***************************************************************************************
函数名称: void PORT_Init(void)
功能描述: 初始化I/O
输入: 无
输出: 无
全局变量: XBR2,P74OUT
调用模块: 无
***************************************************************************************/
//void PORT_Init (void)
//{
// XBR2 = 0x40; /*使能交叉开关和弱上拉*/
// P74OUT |= 0xff; /*使能P6,P7推挽输出*/
//}
void Play(char * str)
{
uchar i=0,ch,halfflg=0;
uchar lasttime;
uint freq;
/*无效看门狗*/
// WDTCN = 0xde;
// WDTCN = 0xad;
// PORT_Init ();
// OSCICN=0x14; /*使用内部晶振*/
while(1)
{
for(;;i++)
{
ch=str[i]; /*允许曲谱用空格符 '|'符,换行回车等分隔以便阅读*/
if((ch==' ')||(ch=='|')||(ch=='\r')||(ch=='\n')) {i++;continue;}
if(!ch) {SoundOff(); return;} /*乐曲结束则播放完毕*/
if(ch=='#') {halfflg=1; continue;} /*半音标志*/
if(isdigit(ch)||isalpha(ch))
{
freq=GetFreq(ch,halfflg); /*从音名获取频率*/
lasttime=16;
break;
}
else {halfflg=0; continue;}
}
i++;
ch=str[i]; /*从下一个符号获取额外音长符号*/
while(1)
{
if(!ch) break;
if(isdigit(ch)||isalpha(ch)) break; /*非音长符号则下次处理*/
if(ch=='-') lasttime+=8; /*额外延时一拍*/
if(ch=='.') lasttime+=4; /*额外延时半拍*/
if(ch=='_') lasttime/=2; /*下划线相当于简谱中音名下面的下划线,延时减半*/
if(ch=='=') lasttime/=4; /*双下划线相当于简谱中音名下面的双下划线,延时减为1/4*/
i++;
ch=str[i];
}
if(freq!=0) Sound(freq); /*发声*/
else SoundOff();
delay2(lasttime); /*延时*/
SoundOff();
delay2(1); /*两个引之间的间歇*/
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -