📄 pwm2.c.bak
字号:
/**********************************************************************
* *功能描述:PWM试验2,利用C8051F310内部PWM,从P2.0输出一定脉宽的波波
* * 从而产生音乐。
***********************************************************************/
#include <c8051F310.h> //C8051F31X系列头文件。
#define SYSCLK 24500000 // SYSCLK frequency in 24.5 MHz
#define T1_18ms 65536L - 6 * (SYSCLK / 4000L)
#define TH1S T1_18ms >> 8
#define TL1S T1_18ms
//*********************************************************************
//变量定义
//*********************************************************************
unsigned char music; //歌曲指针
unsigned char yf=0; //音符
unsigned char pm=0; //拍码,拍数
unsigned char td=0; //停顿
unsigned char gq; //歌曲选择
//////////////////////////////////////////////////////////////////////
//*********************************************************************
//歌曲
//*********************************************************************
code unsigned char tab[5][250] = {
{0x82, 0x01, 0x81, 0x94, 0x84, //生日快乐
0xb4, 0xa4, 0x04,
0x82, 0x01, 0x81, 0x94, 0x84,
0xc4, 0xb4, 0x04,
0x82, 0x01, 0x81, 0xf4, 0xd4,
0xb4, 0xa4, 0x94,
0xe2, 0x01, 0xe1, 0xd4, 0xb4,
0xc4, 0xb4, 0x04,
0x82, 0x01, 0x81, 0x94, 0x84,
0xb4, 0xa4, 0x04,
0x82, 0x01, 0x81, 0x94, 0x84,
0xc4, 0xb4, 0x04,
0x82, 0x01, 0x81, 0xf4, 0xd4,
0xb4, 0xa4, 0x94,
0xe2, 0x01, 0xe1, 0xd4, 0xb4,
0xc4, 0xb4, 0x04, 0x00},
{0x44, 0x54, 0x64,0x44, //两只老虎
0x44, 0x54, 0x64,0x44,
0x64, 0x74, 0x88,
0x64, 0x74, 0x88,
0x82, 0x92, 0x82, 0x72, 0x64, 0x44,
0x82, 0x92, 0x82, 0x72, 0x64, 0x44,
0x44, 0x84, 0x48,
0x44, 0x14, 0x48,
0x44, 0x54, 0x64,0x44,
0x44, 0x54, 0x64,0x44,
0x64, 0x74, 0x88,
0x64, 0x74, 0x88,
0x82, 0x92, 0x82, 0x72, 0x64, 0x44,
0x82, 0x92, 0x82, 0x72, 0x64, 0x44,
0x44, 0x84, 0x48,
0x44, 0x14, 0x48, 0x00},
{0x64, 0x64, 0x52, 0x42, //把根留住
0x28, 0x12, 0x22,
0x44, 0x44, 0x22, 0x12,
0xfb,
0x54, 0x54, 0x24,
0x64, 0x56, 0x22,
0x6b,
0x6b,
0x64, 0x64, 0x52, 0x42,
0x28, 0x12, 0x22,
0x44, 0x44, 0x22, 0x12,
0xfb,
0x54, 0x54, 0x24,
0x64, 0x56, 0x12,
0x2b,
0x2b,
0x64, 0x64, 0x52, 0x42,
0x28, 0x12, 0x22,
0x44, 0x44, 0x22, 0x12,
0xfb,
0x54, 0x54, 0x24,
0x64, 0x56, 0x22,
0x6b,
0x6b,
0x64, 0x64, 0x52, 0x42,
0x28, 0x12, 0x22,
0x44, 0x44, 0x22, 0x12,
0xfb,
0x54, 0x54, 0x24,
0x64, 0x56, 0x12,
0x2b,
0x2b,
0x13, 0x21, 0x12, 0x12, 0x12, 0x22,
0x48, 0x64,
0x52, 0x62, 0x52, 0x22, 0x52, 0x82,
0x6b,
0x94, 0x94, 0xa2, 0x94,
0x88, 0x54,
0x6b,
0x6b,
0x94, 0x94, 0x92, 0x82,
0x88, 0x82, 0x52,
0x66, 0x82, 0x52, 0x62,
0x2b,
0x54, 0x86, 0x62,
0x58, 0x52, 0x62,
0x2b,
0x24, 0x04, 0x04,
0x54, 0x86, 0x62,
0x58, 0x84,
0x9b, 0x9b, 0x9b, 0x00},
{0x02, 0x12, 0x42, 0x32, //童话
0x43, 0x11, 0x14, 0x02, 0x12, 0x42, 0x32,
0x43, 0x11, 0x14, 0x02, 0x12, 0x42, 0x32,
0x46, 0x42, 0x42, 0x22, 0x22, 0x12,
0x18, 0x02, 0x12, 0x42, 0x32,
0x42, 0x12, 0x14, 0x02, 0x12, 0x63, 0x51,
0x52, 0x42, 0x44, 0x02, 0x12, 0x42, 0x32,
0x42, 0x22, 0x02, 0x22, 0x22, 0x42, 0x92, 0x82,
0x88, 0x02, 0x52, 0x52, 0x72,
0x72, 0x62, 0x64, 0x02, 0x62, 0x52, 0x32,
0x53, 0x41, 0x42, 0x31, 0x41, 0x02, 0x42, 0x32, 0x42,
0x74, 0x02, 0x12, 0x82, 0x72, 0x62, 0x52,
0x58, 0x02, 0x52, 0x52, 0x72,
0x72, 0x62, 0x64, 0x02, 0x62, 0x62, 0xa2,
0xa2, 0x92, 0xa2, 0xb2, 0x02, 0xb2, 0x52, 0x42,
0x96, 0x92, 0x92, 0x82, 0x82, 0x82,
0x88, 0x02, 0x12, 0x82, 0x72,
0x64, 0x62, 0x71, 0x61, 0x64, 0x62, 0x72,
0x62, 0x72, 0x62, 0x51, 0x41, 0x02, 0x42, 0x62, 0x82,
0x94, 0x92, 0x91, 0x81, 0x82, 0x52, 0x52, 0x71, 0x61,
0x68, 0x02, 0x42, 0x62, 0x82,
0x94, 0x92, 0x91, 0x81, 0x52, 0x52, 0x52, 0x72,
0x62, 0x72, 0x62, 0x51, 0x41, 0x44, 0x52, 0x51, 0x61,
0x24, 0x22, 0x42, 0x42, 0x32, 0x34,
0x48, 0x00 },
{0x04, 0x04, 0x02, 0x42, 0x42, 0x52, //昨日重现
0x64, 0x84, 0x82, 0x62, 0x82, 0x62,
0x94, 0x84, 0x64, 0x62, 0x82,
0x94, 0x54, 0x62, 0x86,
0x98, 0x04, 0x62, 0x82,
0x94, 0xd4, 0xc2, 0xb4, 0xa2,
0xa6, 0x82, 0x62, 0x84, 0x64, 0x5b}
};
//**********************************************************************
//函数名:void PORT_Init (void)
//功能描述:端口初始化。
//**********************************************************************
void PORT_Init (void)
{
P2MDOUT = 0x01; // P2.0为输出。
P0SKIP = 0XFF;
P1SKIP = 0X7F;
XBR0 = 0x00; //硬件UART。
XBR1 = 0xC2; //弱上拉关,交叉开关使能,CEX1使能。
}
//**********************************************************************
//函数名:void Internal_Crystal(void)
//功能描述:设定内部时钟。
//**********************************************************************
void Internal_Crystal(void)
{
OSCICN = 0x83; // 内部振荡器允许,不分频最快频率
CLKSEL = 0x00; // 使用内部振荡器。
}
//**********************************************************************
//函数名:void PWMInit(void)
//功能描述:PWM初始化。
//**********************************************************************
void PWMInit(void)
{
PCA0CN = 0X40; //允许PCA计数定时器工作。
// PCA0MD |= 0X04;
// PCA0MD &= ~0X0A; //频率由TIMER0决定。
PCA0MD = 0x04;
PCA0CPM1 = 0X42; //允许PCA比较功能,8位PWM允许。
PCA0CPL1 = 0X80; //
PCA0CPH1 = 0X80; //占空比为50%。
}
//**********************************************************************
//函数名:void Timer0_Init (void)
//功能描述:初始化定时器0
//**********************************************************************
void Timer0_Init (void)
{
CKCON = 0x01; // 使用系统时钟4分频
TMOD &= ~0x0F;
TMOD |= 0x02; // 8位,方式2
ET0 = 0; //不用进入中断 TR0 = 0; // 停止
}
//**********************************************************************
//函数名:void Timer1_Init (void)
//功能描述:初始化定时器1
//**********************************************************************
void Timer1_Init (void)
{
CKCON = 0x01; // 使用系统时钟不分频
TMOD &= 0X0F;
TMOD |= 0x10; // 16位定时器。
TL1 = TL1S;
TH1 = TH1S; //
ET1 = 1; // 使能Timer0中断。
TR1 = 0; // 停止
}
/***********************************************************************************
//函数名:void Play(unsigned char m)
//功能描述:发出该音符的声音。
/*********************************************************************************/
void Play(unsigned char m)
{
switch(m)
{
case 0:
TR0 = 0;
break;
case 1:
TR0 = 0;
TH0 = 195;
TL0 = 195;
TR0 = 1;
break;
case 2:
TR0 = 0;
TH0 = 202;
TL0 = 202;
TR0 = 1;
break;
case 3:
TR0 = 0;
TH0 = 208;
TL0 = 208;
TR0 = 1;
break;
case 4:
TR0 = 0;
TH0 = 211;
TL0 = 211;
TR0 = 1;
break;
case 5:
TR0 = 0;
TH0 = 215;
TL0 = 215;
TR0 = 1;
break;
case 6:
TR0 = 0;
TH0 = 220;
TL0 = 220;
TR0 = 1;
break;
case 7:
TR0 = 0;
TH0 = 222;
TL0 = 222;
TR0 = 1;
break;
case 8:
TR0 = 0;
TH0 = 225;
TL0 = 225;
TR0 = 1;
break;
case 9:
TR0 = 0;
TH0 = 229;
TL0 = 229;
TR0 = 1;
break;
case 10:
TR0 = 0;
TH0 = 232;
TL0 = 232;
TR0 = 1;
break;
case 11:
TR0 = 0;
TH0 = 233;
TL0 = 233;
TR0 = 1;
break;
case 12:
TR0 = 0;
TH0 = 236;
TL0 = 236;
TR0 = 1;
break;
case 13:
TR0 = 0;
TH0 = 238;
TL0 = 238;
TR0 = 1;
break;
case 14:
TR0 = 0;
TH0 = 239;
TL0 = 239;
TR0 = 1;
break;
case 15:
TR0 = 0;
TH0 = 241;
TL0 = 241;
TR0 = 1;
break;
}
}
//**********************************************************************
//函数名:void Timer0_ISR (void) interrupt 1
//功能描述:定时器0中断函数。
//**********************************************************************
void Timer1_ISR (void) interrupt 3 //18ms
{
static unsigned char count;
unsigned char temp;
TF1 = 0;
TL1 = TL1S;
TH1 = TH1S;
if(++count >= 2)
{
count = 0;
if(pm == 0)
{
if(td == 1) //停顿
{
td = 0;
temp = tab[gq][music];
music++;
if(temp != 0)
{
pm = temp&0x0f; //取拍码
pm *= 10; //中断为1/4拍的1/10
temp >>= 4;
yf = temp&0x0f; //取音符
Play(yf); //该音符的声音
}
else
{
TR0 = 0;
TR1 = 0; //一首歌曲播完后停止
}
}
else
{
td++;
Play(0); //停顿1/4拍
}
}
else
{
pm--;
Play(yf);
}
}
}
main()
{
PCA0MD &= ~0x40; //关闭看门狗。
PORT_Init(); //端口初始化。
Internal_Crystal(); //内部晶体。
Timer0_Init();
Timer1_Init();
PWMInit(); //串口初始化。
// CR = 1; //开启定时器。
EA = 1;
gq = 3;
TR1 = 1;
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -