📄 cpu.c
字号:
//*****************************************************************************
//CPU.C
//*****************************************************************************
#include "mydefine.h"
///////////////////////////////////////////////////////////////////////////////
#define SYSCLK 24500000 // SYSCLK frequency in 24.5 MHz
#define T1_18ms 65536L - 1 * (SYSCLK / 4000L)
#define TH1S T1_18ms >> 8
#define TL1S T1_18ms
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
unsigned int TimeOutCounts[3];
extern unsigned char DisplayBuf[6];
unsigned char music; //歌曲指针
unsigned char yf=0; //音符
unsigned char pm=0; //拍码,拍数
unsigned char td=0; //停顿
extern unsigned char gq; //歌曲选择
extern unsigned char run; //歌曲运行与否
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//段码
//////////////////////////////////////////////////////////////////////////////
code INT8U SegmentCode[28]={
0X3F,//0
0X06,//1
0X5B,//2
0X4F,//3
0X66,//4
0X6D,//5
0X7D,//6
0X07,//7
0X7F,//8
0X6F,//9
0X77,//A
0X7C,//b
0X39,//C
0X58,//c
0X5E,//d
0X79,//E
0X71,//F
0X76,//H
0X74,//h
0X38,//L
0X73,//P
0X78,//t
0X40,//-
0x00,//nop
0x50,//r
0x1c,//u
0x54,//n
0x37//N
};
////////////////////////////////////////////////////////////////////////////////
//*********************************************************************
//歌曲
//*********************************************************************
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)
{
P0MDOUT = 0x13; // SDA,SCL,TXD:OUT /EXD,INT0,INT1:IN
P1MDOUT = 0xff; // LED/SEG:OUT
P2MDOUT = 0xFB; // ADC0:IN
P3MDOUT = 0X16; //SCK1:IN
P0SKIP = 0XFF;
P1SKIP = 0X7F;
XBR0 = 0x00; //硬件UART,SPI使能。
XBR1 = 0xC2; //弱上拉开,交叉开关使能。
}
//*****************************************************************************
//函数名:void Internal_Crystal(void)
//功能描述:设定内部时钟。
//*****************************************************************************
void Internal_Crystal(void)
{
OSCICN = 0x83; // 内部振荡器允许,不分频最快频率
CLKSEL = 0x00; // 使用内部振荡器。
}
//**********************************************************************
//函数名:void Timer0_Init (void)
//功能描述:初始化定时器0,PCA时钟是以定时器0溢出率为时钟的。
//**********************************************************************
void Timer0_Init (void)
{
CKCON = 0x01; // 使用系统时钟4分频
TMOD &= ~0x0F;
TMOD |= 0x02; // 8位,方式2
ET0 = 0; //不用进入中断
TR0 = 0; // 停止
}
//**********************************************************************
//函数名:void PWMInit(void)
//功能描述:PWM初始化。
//**********************************************************************
void PWMInit(void)
{
PCA0CN = 0X40; //允许PCA计数定时器工作。
PCA0MD = 0x04;
PCA0CPM1 = 0X42; //允许PCA比较功能,8位PWM允许。
PCA0CPL1 = 0X80; //
PCA0CPH1 = 0X80; //占空比为50%。
}
//**********************************************************************
//函数名:void Timer1_Init (void)
//功能描述:初始化定时器1
//**********************************************************************
void Timer1_Init (void)
{
CKCON = 0x01; // 使用系统时钟不分频
TMOD &= 0X0F;
TMOD |= 0x10; // 16位定时器。
TL1 = TL1S;
TH1 = TH1S; //
ET1 = 1; // 使能Timer1中断。
TR1 = 0; // 停止
}
//******************************************************************************
//函数名:unsigned int ReadTimer(unsigned char n)
//功能描述:软件计时器
//******************************************************************************
unsigned int ReadTimer(unsigned char n)
{
unsigned char temp;
ET1 = 0;
temp = TimeOutCounts[n]; //读出时间
ET1 = 1;
return temp;
}
//******************************************************************************
//函数名:void ResetTimer(unsigned char n)
//功能描述:复位计时器
//******************************************************************************
void ResetTimer(unsigned char n)
{
ET1 = 0;
TimeOutCounts[n & 0x03] = 0;
ET1 = 1;
}
//******************************************************************************
//函数名:unsigned char SpiReadWrite(unsigned char dat)
//功能描述:SPI发送接收一个数据。
//******************************************************************************
unsigned char SpiReadWrite(unsigned char dat)
{
unsigned char i,temp;
temp = 0;
SCK = 0;
_nop_();
for(i=0; i<8; i++)
{
if(dat & 0x80)
{
MOSI = 1;
}
else MOSI = 0;
dat <<= 1;
SCK = 1;
_nop_();
_nop_();
_nop_();
_nop_();
temp <<= 1;
if(MISO)temp++;
SCK = 0;
_nop_();
_nop_();
_nop_();
_nop_();
}
return temp;
}
/***********************************************************************************
//函数名:void Play(unsigned char m)
//功能描述:发出该音符的声音。
/*********************************************************************************/
void Play(unsigned char m)
{
switch(m)
{
case 0:
TR0 = 0;//停顿
break;
case 1:
TR0 = 0;//低音5
TH0 = 195;
TL0 = 195;
TR0 = 1;
break;
case 2:
TR0 = 0;
TH0 = 202;
TL0 = 202;
TR0 = 1;//低音6
break;
case 3:
TR0 = 0;
TH0 = 208;
TL0 = 208;
TR0 = 1;//低音7
break;
case 4:
TR0 = 0;
TH0 = 211;
TL0 = 211;
TR0 = 1;//中音1
break;
case 5:
TR0 = 0;
TH0 = 215;
TL0 = 215;
TR0 = 1;//中音2
break;
case 6:
TR0 = 0;
TH0 = 220;
TL0 = 220;
TR0 = 1;//中音3
break;
case 7:
TR0 = 0;
TH0 = 222;
TL0 = 222;
TR0 = 1;//中音4
break;
case 8:
TR0 = 0;
TH0 = 225;
TL0 = 225;
TR0 = 1;//中音5
break;
case 9:
TR0 = 0;
TH0 = 229;
TL0 = 229;
TR0 = 1;//中音6
break;
case 10:
TR0 = 0;
TH0 = 232;
TL0 = 232;
TR0 = 1;//中音7
break;
case 11:
TR0 = 0;
TH0 = 233;
TL0 = 233;
TR0 = 1;//高音1
break;
case 12:
TR0 = 0;
TH0 = 236;
TL0 = 236;
TR0 = 1;//高音2
break;
case 13:
TR0 = 0;
TH0 = 238;
TL0 = 238;
TR0 = 1;//高音3
break;
case 14:
TR0 = 0;
TH0 = 239;
TL0 = 239;
TR0 = 1;//高音4
break;
case 15:
TR0 = 0;
TH0 = 241;
TL0 = 241;
TR0 = 1;//高音5
break;
}
}
//*****************************************************************************
//函数名:void SelWM(INT8U tt)
//功能描述:选择数码管位码。
//*****************************************************************************
void SelWM(INT8U tt)
{
LATCH_595 = 0;
switch(tt)
{
case 0:
SpiReadWrite(0xdf);
break;
case 1:
SpiReadWrite(0xef);
break;
case 2:
SpiReadWrite(0xf7);
break;
case 3:
SpiReadWrite(0xfb);
break;
case 4:
SpiReadWrite(0xfd);
break;
case 5:
SpiReadWrite(0xfe);
break;
case 0xff:
SpiReadWrite(0xff);
break;
}
LATCH_595 = 1;
}
//**********************************************************************
//函数名:void Timer0_ISR (void) interrupt 1
//功能描述:定时器0中断函数。
//**********************************************************************
void Timer1_ISR (void) interrupt 3
{
static unsigned char count;
static unsigned char WM = 0;
unsigned char temp;
TF1 = 0;
TL1 = TL1S;
TH1 = TH1S;
TimeOutCounts[0]++;
TimeOutCounts[1]++;
TimeOutCounts[2]++;
P1 = 0;
SelWM(WM);
P1 = SegmentCode[DisplayBuf[WM]];//数码管显示
if(++WM == 6)
WM = 0;
if((++count >= 12) && (run == 1))
{
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);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -