#include <STC12C5A60S2.H> //单片机头文件
sbit led = P0^0;
sbit code0 =P0^1;
sbit code1 =P0^2;
sbit code2 =P0^3;
//VS1003IO
sbit XRESET =P0^7;
sbit DREQ =P0^4;
sbit XCS =P0^6;
sbit XDCS =P0^5;
//SD卡IO
sbit CLK = P3^4;//同步时钟
sbit DI = P3^5;//Cmd/DataIn
sbit DO = P3^6;//DataOut
sbit CS = P3^7;//片选
void delay_ms(int i){
int a,b;
for(a=0;a<i;a++){
for(b=0;b<600;b++);
};
}
//******************vs1003操作*************************************************************************************************
//初始化spi
void init_spi(void){
SPCTL = 0xdd;//忽略SS,设置主机,spi高位先发送
SPSTAT = 0xc0;//清除状态寄存器
SPDAT = 0;//初始化数据寄存器
}
void spi_write(unsigned char sendData){
SPDAT = sendData;
while((SPSTAT&0x80)==0);
SPSTAT = 0xc0;//清除状态寄存器
SPSTAT = 0;
}
void delay(unsigned int time)
{
while(time--);
}
void wr_command(unsigned char addr,unsigned char hdat,unsigned char ldat )
{
DREQ=1;
while(!DREQ);
XCS=0;
spi_write(0x02);
spi_write(addr);
spi_write(hdat);
spi_write(ldat);
XCS=1;
}
//vs1003初始化
void Mp3Reset(void)
{
XRESET=0;
delay(100);
XDCS=XCS=XRESET=1;
wr_command(0x00,0x08,0x04);
delay(10);
DREQ=1;
while(!DREQ);
wr_command(0x03,0x98,0x00);
delay(10);
wr_command(0x05,0xbb,0x81);
delay(10);
wr_command(0x02,0x00,0x55);
delay(10);
wr_command(0x0b,0x2e,0x2e); // 音量
delay(10);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(0);
}
//向VS1003写入一个字节的音频数据,写之前要打开XDCS片选,XDCS=0
void send_dat(unsigned char dat)
{
DREQ=1;
while(!DREQ);//VS1003的DREQ为高才能写入数据
spi_write(dat);//通过SPI向VS1003写入一个字节的音频数据
}
//************************SD卡操作********************************************************************************8
//***********模拟spi写函数
void SPI_W(unsigned char Data){
unsigned char i;
for(i = 0; i<8; i++){
Data <<= 1;
CLK = 0;
DI = CY;
CLK = 1;
};
DI = 1;
}
//***********spi读函数
unsigned char SPI_R(){
unsigned char Data,i;
DO = 1;//设置DO接口为输入状态
for(i = 0; i<8; i++){
Data <<= 1;
CLK = 0;
CLK = 1;
Data |= DO;
};
return Data;
}
//**************读sd卡回应
unsigned char SD_Response(){
unsigned char i,Response;
for(i = 0; i<10; i++){
Response = SPI_R();
if(Response == 0x00)
break;
if(Response == 0x01)
break;
};
return Response;
}
//***************向SD发命令
void SD_Cmd(unsigned char Cmd, unsigned long Argument, unsigned char CRC){
unsigned char arg[4];
arg[0] = (unsigned char)Argument;
arg[1] = (unsigned char)(Argument >> 8);
arg[2] = (unsigned char)(Argument >> 16);
arg[3] = (unsigned char)(Argument >> 24);
SPI_W(Cmd | 0x40);
SPI_W(arg[3]);
SPI_W(arg[2]);
SPI_W(arg[1]);
SPI_W(arg[0]);
SPI_W(CRC);
}
//*************SD卡初始化
unsigned char SD_Init(){
unsigned int delay = 0;
unsigned char i;
unsigned char Response = 0xff;
CS = 1;
for(i = 0; i<10; i++){
SPI_W(0xff);//上电后给74个以上的时间脉冲
};
CS = 0;
SD_Cmd(0x00, 0, 0x95);//命令CMD0,复位SD卡
//等待复位成功
i = 0;
while(SD_Response() != 0x01){//等待SD卡回应信号
i++;
if(i > 100){
return 0;//失败返回0
};
};
CS = 1;
SPI_W(0xff);//关片选后写8个空脉冲,SD卡复位完毕
//设置SPI
i = 0;
CS = 0;
while(Response != 0x00){//循环等待成功回应,若成功,回应信号为0x00
SD_Cmd(0x01, 0, 0xff);//CMD1,将SD卡设置为SPI模式,无需CRC校验,填入0xff
Response = SD_Response();
if(i > 100){
return 0;//尝试100次,失败返回0
};
};
CS = 1;
SPI_W(0xff);//给8个空脉冲
return 1;
}
//****************从sd卡读数据块
void SD_Block_R(unsigned char* block, unsigned long address){
unsigned int i;
CS = 0;
SD_Cmd(0x11, address, 0xff);//CMD11,数据块读写命令,
while(SD_Response()!=0x00);//循环等待命令回应0x00
while(SPI_R() != 0xfe); //0xfe为块读出的头, 后面紧跟512字节的数据块+2字节的CRC
for(i=0; i<512 ; i++){
block[i] = SPI_R();//读数据
};
SPI_R();
SPI_R();//两个字节的CRC。舍弃
CS =1;
SPI_R();//8个空脉冲
}
//************************串口操作********************************************************************************8
void main(){
unsigned char xdata block[512];
int i;
unsigned long adr = 0x3b000;
unsigned long len = 0;
unsigned char mp3Name = 0x30;
led=0;
delay_ms(5000);
led=1;
//等待2秒使相片稳定
delay_ms(5000);
if(code0==0){mp3Name=mp3Name+1;};
if(code1==0){mp3Name=mp3Name+2;};
if(code2==0){mp3Name=mp3Name+4;};
//如果扫到的编码大于0(防止误操作)
if(mp3Name>0x30){
//初始化spi
init_spi();
//初始化sd卡
SD_Init();
//初始化vs1003
Mp3Reset();
delay_ms(1000);
led=0;
SD_Block_R(block,adr);
//在SD卡的FAT中找到该MP3
for(i=0;i<512;i=i+16){
if(block[i]==0x28){
if(block[i+1]==mp3Name){
if(block[i+2]==0x29){
break;
};
};
};
};
//如果找到该MP3文件
if(i<500){
//计算MP3文件的地址和长度
adr=block[i+26]+block[i+27]*256;
adr=adr*64+376;
adr=adr*512;
len = block[i+28] + block[i+29]*256 + block[i+30]*65536 + block[i+31]*16777216;
len=len/512+1;
//循环播放
XDCS=0;
while(1){
unsigned long address = adr;
unsigned long ii;
for(ii=0;ii<len;ii++){
SD_Block_R(block,address+=512);
for(i=0;i<512;i++){
send_dat(block[i]);
};
};
delay_ms(20000);
};
};
};
//如果没有相片的解码小于0或SD卡中没找到该MP3文件,灯闪烁
while(1){
led=~led;
delay_ms(8000);
};
}