//正弦测试 void VS_Sine_Test(void) { VS_HD_Reset(); VS_WR_Cmd(0x0b, 0X2020); //设置音量 VS_WR_Cmd(SPI_MODE, 0x0820); //进入VS10XX的测试模式 while (VS_DQ == 0); //等待DREQ为高 //printf("mode sin:%x\n",VS_RD_Reg(SPI_MODE)); //向VS10XX发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00 //其中n = 0x24, 设定VS10XX所产生的正弦波的频率值,具体计算方法见VS10XX的datasheet VS_SPI_SpeedLow();//低速 VS_XDCS_L; //选中数据传输 VS_SPI_ReadWriteByte(0x53); VS_SPI_ReadWriteByte(0xef); VS_SPI_ReadWriteByte(0x6e); VS_SPI_ReadWriteByte(0x24); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS_H; //退出正弦测试 VS_XDCS_L; //选中数据传输 VS_SPI_ReadWriteByte(0x45); VS_SPI_ReadWriteByte(0x78); VS_SPI_ReadWriteByte(0x69); VS_SPI_ReadWriteByte(0x74); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS_H; //再次进入正弦测试并设置n值为0x44,即将正弦波的频率设置为另外的值 VS_XDCS_L; //选中数据传输 VS_SPI_ReadWriteByte(0x53); VS_SPI_ReadWriteByte(0xef); VS_SPI_ReadWriteByte(0x6e); VS_SPI_ReadWriteByte(0x44); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS_H; //退出正弦测试 VS_XDCS_L; //选中数据传输 VS_SPI_ReadWriteByte(0x45); VS_SPI_ReadWriteByte(0x78); VS_SPI_ReadWriteByte(0x69); VS_SPI_ReadWriteByte(0x74); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(100); VS_XDCS_H; }
//ram 测试 //返回值:RAM测试结果 // VS1003如果得到的值为0x807F,则表明完好;VS1053为0X83FF. u16 VS_Ram_Test(void) { VS_HD_Reset(); VS_WR_Cmd(SPI_MODE, 0x0820); // 进入VS10XX的测试模式 while (VS_DQ == 0); // 等待DREQ为高 VS_SPI_SpeedLow();//低速 VS_XDCS_L; // xDCS_H,选择VS10XX的数据接口 VS_SPI_ReadWriteByte(0x4d); VS_SPI_ReadWriteByte(0xea); VS_SPI_ReadWriteByte(0x6d); VS_SPI_ReadWriteByte(0x54); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); VS_SPI_ReadWriteByte(0x00); delay_ms(150); VS_XDCS_H; return VS_RD_Reg(SPI_HDAT0);// VS1003如果得到的值为0x807F,则表明完好;VS1053为0X83FF.; }
//切歌 //通过此函数切歌,不会出现切换“噪声” void VS_Restart_Play(void) { u16 temp; u16 i; u8 n; u8 vsbuf[32]; for (n = 0; n < 32; n++) vsbuf[n] = 0; //清零 temp = VS_RD_Reg(SPI_MODE); //读取SPI_MODE的内容 temp |= 1 << 3; //设置SM_CANCEL位 temp |= 1 << 2; //设置SM_LAYER12位,允许播放MP1,MP2 VS_WR_Cmd(SPI_MODE, temp); //设置取消当前解码指令 for (i = 0; i < 2048;) //发送2048个0,期间读取SM_CANCEL位.如果为0,则表示已经取消了当前解码 { if (VS_Send_MusicData(vsbuf) == 0) //每发送32个字节后检测一次 { i += 32; //发送了32个字节 temp = VS_RD_Reg(SPI_MODE); //读取SPI_MODE的内容 if ((temp & (1 << 3)) == 0) break; //成功取消了 } } if (i < 2048) //SM_CANCEL正常 { temp = VS_Get_EndFillByte() & 0xff; //读取填充字节 for (n = 0; n < 32; n++) vsbuf[n] = temp; //填充字节放入数组 for (i = 0; i < 2052;) { if (VS_Send_MusicData(vsbuf) == 0) i += 32; //填充 } } else VS_Soft_Reset(); //SM_CANCEL不成功,坏情况,需要软复位 temp = VS_RD_Reg(SPI_HDAT0); temp += VS_RD_Reg(SPI_HDAT1); if (temp) //软复位,还是没有成功取消,放杀手锏,硬复位 { VS_HD_Reset(); //硬复位 VS_Soft_Reset(); //软复位 } }
//初始化VS10XX的IO口 void VS_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; //DREQ PC.7 RCC_APB2PeriphClockCmd(VS_DQ_RCC, ENABLE); //使能Px端口时钟 GPIO_InitStructure.GPIO_Pin = VS_DQ_PIN; //PC.7 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(VS_DQ_GPIO, &GPIO_InitStructure); //RES PE.0 RCC_APB2PeriphClockCmd(VS_RST_RCC, ENABLE); //使能Px端口时钟 GPIO_InitStructure.GPIO_Pin = VS_RST_PIN; //PE6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 GPIO_Init(VS_RST_GPIO, &GPIO_InitStructure); //CS PB.12 RCC_APB2PeriphClockCmd(VS_XCS_RCC, ENABLE); //使能Px端口时钟 GPIO_InitStructure.GPIO_Pin = VS_XCS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(VS_XCS_GPIO, &GPIO_InitStructure); //XDCS PC.6 RCC_APB2PeriphClockCmd(VS_XDCS_RCC, ENABLE); //使能Px端口时钟 GPIO_InitStructure.GPIO_Pin = VS_XDCS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_Init(VS_XDCS_GPIO, &GPIO_InitStructure); SPI_INIT(); VS_Sine_Test(); //USART_OUT(DEBUG_USART, "Ram Test:0X%04X\r\n", VS_Ram_Test()); //打印RAM测试结果 VS_HD_Reset(); VS_Soft_Reset(); VS_Restart_Play(); //重启播放 VS_Set_All(); //设置音量等信息 VS_Reset_DecodeTime(); //复位解码时间 VS_SPI_SpeedHigh(); //高速 VS_Set_Vol(250); }
//播放一曲指定的歌曲 //pname:歌曲路径+名字 //返回值:0,正常播放完成 // 1,下一曲 // 2,上一曲 // 0XFF,出现错误了 u8 MP3_playSong(const char *pName) { FIL* fmp3; u16 br; u8 res,rval; u8 *databuf; u16 i=0; u8 key; //static u8 pause=0; //暂停标志 static u8 lastVol = 0; //上一次音量 //u8 j = 0; rval=0; fmp3=(FIL*)malloc(sizeof(FIL)); //申请内存 databuf=(u8*)malloc(READ_MP3_SIZE); //开辟4096字节的内存区域 if(databuf==NULL||fmp3==NULL)rval=0XFF ;//内存申请失败. if(rval==0) { VS_HD_Reset(); VS_Soft_Reset(); lastVol = vsset.mvol; mp3_vol_show((vsset.mvol-100)/5); //音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30 VS_Restart_Play(); //重启播放 VS_Set_All(); //设置音量等信息 VS_Reset_DecodeTime(); //复位解码时间 /*res=f_typetell(pname); //得到文件后缀 if(res==0x4c)//如果是flac,加载patch { VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN); } */ res=f_open(fmp3,(const TCHAR*)pName,FA_READ);//打开文件 //printf("sram :%d",mem_perused(0)); if(res==0)//打开成功. { VS_SPI_SpeedHigh(); //高速 while(rval==0) { res=f_read(fmp3,databuf,READ_MP3_SIZE,(UINT*)&br);//读出4096个字节 i=0; if (lastVol != vsset.mvol) //检测音量是否重新配置 { VS_Set_Vol(vsset.mvol); lastVol = vsset.mvol; //保存到配置文件 } #if 1 do//主播放循环 { if((VS_Send_MusicData(databuf+i)==0))//给VS10XX发送音频数据 { i+=32; } else { key=KEY_getValue(); switch(key) { case KEY_UP: printf("+++++++++++++++++++++++++++key up\r\n"); rval=KEY_UP; //跳出 break; default: break; } //mp3_msg_show(fmp3->fsize);//显示信息 } }while(i<READ_MP3_SIZE);//循环发送4096个字节 #endif if(br!=READ_MP3_SIZE||res!=0) { rval=KEY_UP; break;//读完了. } } f_close(fmp3); }else rval=0XFF;//出现错误 } if (databuf != NULL) free(databuf); if (fmp3 != NULL) free(fmp3); return rval; }