本帖最后由 hongniu 于 2015-6-23 16:50 编辑
MP3在之前对我来说是一个很深奥,很高级的东西!感性的认识就是前年买的那个MP3。说起MP3不得不说LCD12864,他起得头,自从做完12864显示后,我目标瞄向了彩屏!黑白屏有啥意思!彩色的才好来!于是又做TFT9325彩屏!在做彩屏之前做了一件非常非常重要的事!因为彩屏不同于12864,12864显示一整屏才要1024个字节,而彩屏2.4寸则要他的150倍!这么大的数据量你放哪?是个问题吧!这个东西必须要常见,必须要小,必须要容量大!他是什么呢?--没错,就是日常生活中的手机里的那张所谓的内存卡(人家叫TF卡)!第一他常见,第二他小,第三容量大,基本上是1个G的!那个卡只有指甲盖大小!很方便,所有条件满足!就是他了!开始看关于TF卡的资料,首先是文件系统!实话当时我头都大了!啥叫文件系统?什么原理?存储机制是什么?有哪些操作?答案没有现成的!但是资料告诉我们只要坚持一定会找到!慢慢的磨啊磨啊!开始知道我要学的文件系统没名字叫FAT32文件系统!开始了解内部逻辑扇区和MBR,BPB,根目录,FAT表,数据链,簇,扇区,通信机制,数据读写,命令/指令,可是光有这些还是不行,要试验,要调试,失败,失败,失败,连着一个星期的失败换来了成功,知道有一天,我记得特别清楚我从TF卡中读到了55AA,那代表了扇区的结束标志,可是期待的EB(逻辑0扇区标志)没有出现,又一次失落了,怀疑,我读错了?还是......。不懂了,第二天我做了个通信,把数据一次性的送往计算机,到数据送出的那一刻,我激动了,我明白了,原来我读出的并不是逻辑0扇区,而是物理0扇区,以前的思想多磨可笑啊!再次基础上我成功的读出逻辑0扇区!跟实际的一摸一样,这意味这我可以对TF卡的在地址范围内的任意一个地址扇区进行读取!TF卡的底层已经对我打开了!这时我放下TF卡,专攻彩屏液晶显示器!又是失败,失败,失败,失败,两个星期后我终于可以在彩屏的任意点显示任意颜色!接下来是把TF卡和液晶连起来!把JPG的320240的图像转换成BMP的16位图像,转成BIN,存到TF卡中,找到数据地址,吧数据地址送到液晶,液晶取出数据以扫描方式显示在屏幕上!读完正好扫描完成!正好是一幅完整的图像!当然速度是很慢的!因为CPU实在是不敢恭维啊!但是他做到了!接下来搞啥呢?-----MP3!数据的存储还用TF卡,就凭我的程序水平肯定编不出MP3解码算法的,所以我决定使用专用的DSP解码器,那我要做的是把数据给他!然后让他解码!DA后在耳机里听到音乐!思路是有了!写程序,修改,实验,失败,我目标很明确,任何器件都一样,首先保证硬件是正确的,下一步是底层的驱动是成功的!因为解码器用的通信使SPI,很容易实现,一下午的功夫,搞定了!然后把数据送往MP3解码器,此时在耳机里听到悦耳的音乐!我真的很高兴!因为这是有史以从未搞过的!接下来的几天我开始遇到麻烦了!播放老是得我去计算歌曲的地址,然后告诉他,太麻烦,离显示的MP3还太遥远,于是开始着手改进,当我开始的时候问题来了,MP3的码率不够,导致有的比特流高的歌曲不能播放!又改程序,简化代码,提高速度,这里说一点,指针我头一次用,效率果然不同一般!贼快!码率解决了,怎样让他自己自动的找歌!而不用我人为地计算呢?-----呵呵-----文件系统!---我把我找个歌曲文件的方法换成代码,就是了!程序一运行,感觉一切正常,自动找到歌曲并播放,问题又来了,放着放着乱了,本来是1的却播到2去了!又开始找了一天的原因,第二天才知道原来少了一个变量,哎!曲折啊!又来问题了,我明明在电脑上已经删除的文件他还在播!后来WNHEX才知道原来电脑删除文件时在根目录里吧文件名的第一个字节改成E5,哎呀,有是一顿修改,调试,终于昨天上午全部搞定!现在是一个通过手机TF卡或SD卡存储4G文件为文件内存的,具FAT32文件系统、自动识别MP3文件、自动扫描歌曲目录、自动顺序播放、自动添加MP3文件的准MP3音乐播放器了!!!当然离市面的MP3还差点,但是剩下的工作就是对系统的扩展了!什么音量调整了,进度条了,频谱了,人机界面了!都可以在此基础上做了!!!
于天津开发区第四项目部。
源程序:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar some;
- unsigned long k=4323840;//定义根目录地址,当然我知道;
- uchar xdata tab[512];
- //******************
- sbit p1_7=P1^7;
- sbit CS=P2^0; //片选信号(低电平有效)
- sbit DATEIN =P2^1;//主-从数据输入
- sbit SCLK=P2^2;//时钟信号
- sbit DATEOUT=P2^3;//从-主数据输出
- unsigned char bdata dat;
- sbit dat_0=dat^0;
- sbit dat_1=dat^1;
- sbit dat_2=dat^2;
- sbit dat_3=dat^3;
- sbit dat_4=dat^4;
- sbit dat_5=dat^5;
- sbit dat_6=dat^6;
- sbit dat_7=dat^7;
- bit is_init;//决定是否延时;
- uchar lpp;
- unsigned char fhz;//返回值
- uchar fhz_buff; //读返回值中间量
- //unsigned char xdata tab[512];
- ///*******************以上是SD卡
- /*
- VS1003mp3模块的接口定义
- */
- sbit XRST=P1^0;//复位
- sbit DREQ=P1^1; //数据请求
- sbit XDCS=P1^2; //数据片选
- sbit XCS=P1^3; //命令片选
- /*
- /* VS1003mp3SPI通信接口定义
- */
- sbit SCK=P1^4; //时钟
- sbit SI=P1^5; //串行输入
- sbit SO=P1^6; //串行输出
- //*******************************
- void delay(uint time)
- { while(time)
- time--;
- }
- //***************************
- unsigned char bdata datmp3;
- sbit datmp3_0=datmp3^0;
- sbit datmp3_1=datmp3^1;
- sbit datmp3_2=datmp3^2;
- sbit datmp3_3=datmp3^3;
- sbit datmp3_4=datmp3^4;
- sbit datmp3_5=datmp3^5;
- sbit datmp3_6=datmp3^6;
- sbit datmp3_7=datmp3^7;
-
- ///*************************************以下是MP3模块的程序
- void delay1ms(uint j)//延时100us
- {unsigned char i;
- for(i=j;i;i--)
- {
- }
- }
- void spi_write_mp3_1(uchar h)//SPI写入一个字节,这里是最底层的数据发送!
- {
- datmp3=h;
-
- SI=datmp3_7;
- //为了进一步提高速度我这里采用了顺序结构!全是断桥残雪惹的祸!第一次爱的人播放正常!而断桥残雪不行了!一定尽全力
- SCK=0; //从SD读取和MP3写数据流下手
- SCK=1;
-
- SI=datmp3_6;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_5;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_4;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_3;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_2;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_1;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_0;
-
- SCK=0;
- SCK=1;
-
-
-
-
-
-
-
- }
-
- /*uchar spi_read_mp3()// SPI读取一个字节
- {
- uchar i,read;
- for(i=8;i;i--)
- {
- SCLK=1;
- delay();
- SCLK=0;
- delay();
- read=SO&0x80;
- read=(read<<1);
- }
- SCLK=1;
- return (read);
- }
- */
- void write_comd_mp3(uchar add,uint date)//写入控制命令add地址date是数据注意这里是16位的数据,内部做分开了处理
- {
- uchar h,l;
- l=date;
- h=(date>>8);
- DREQ=1;
- while(!DREQ); //检测MP3模块的忙状态
- XCS=0;
- spi_write_mp3_1(2); //表示写操作
- spi_write_mp3_1(add);
- spi_write_mp3_1(h); //先写高8位
- spi_write_mp3_1(l);
- XCS=1;
-
- }
- void write_date_mp3(uchar dat)//写入音频数据信息这里还有一点是XDCS在此函数外拉低
- {
- DREQ=1;
- while(!DREQ);
- datmp3=dat;
- SI=datmp3_7;
- //为了进一步提高速度我这里采用了顺序结构!全是断桥残雪惹的祸!第一次爱的人播放正常!而断桥残雪不行了!一定尽全力
- SCK=0; //从SD读取和MP3写数据流下手
- SCK=1;
-
- SI=datmp3_6;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_5;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_4;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_3;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_2;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_1;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_0;
-
- SCK=0;
- SCK=1;
-
-
-
-
-
-
-
- }
- void init_mp3() //初始化vs1003
- {
- XRST=1;
- delay1ms(100);
- XRST=0;
- delay1ms(100);
- XRST=1;
- delay1ms(100);
- write_comd_mp3(0x00,0x0804);//模式设置
- write_comd_mp3(0x03,0x9800);//时钟控制
- write_comd_mp3(0x0b,15000);//声音音量控制 00是最大的!!!!!这里也是十六位的!
- XDCS=0;//数据片选
- spi_write_mp3_1(0);
- spi_write_mp3_1(0);
- spi_write_mp3_1(0);
- spi_write_mp3_1(0);
- XDCS=1;
- }
- void sing(uchar fhz)//正选测试
- {
-
-
- write_comd_mp3(0x00,0x0820);
- DREQ=1;
- while(!DREQ);
- XDCS=0;
- write_date_mp3(0x53);
- write_date_mp3(0xef);
- write_date_mp3(0x6e);//正选测试开启
- write_date_mp3(fhz); //频率选择
- write_date_mp3(0);
- write_date_mp3(0);
- write_date_mp3(0);
- write_date_mp3(0);
- delay1ms(60000);
- write_date_mp3(0x45); //正选关段
- write_date_mp3(0x78);
- write_date_mp3(0x69);
- write_date_mp3(0x74);
- write_date_mp3(0);
- write_date_mp3(0);
- write_date_mp3(0);
- write_date_mp3(0);
- XDCS=1;
-
-
-
-
-
- }
- //以上是MP3程序
- //*//**********************************************
-
- /*读sd卡子程序,无返回值,有参函数,参数为要写入DATEIN数据线的字节*/
- void write(unsigned char wr_)// 写入一个字节SD卡
- {
- dat=wr_;
- DATEIN=dat_7;
-
- SCLK=0;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
-
- DATEIN=dat_6;
-
- SCLK=0;
- //if(!is_init)delay(1);
- if(is_init)delay(200);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
- DATEIN=dat_5;
-
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- //if(!is_init)delay(1);
- DATEIN=dat_4;
-
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
- DATEIN=dat_3;
-
- SCLK=0;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
- DATEIN=dat_2;
-
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
- DATEIN=dat_1;
-
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- // if(!is_init)delay(1);
- DATEIN=dat_0;
-
- SCLK=0;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- SCLK=1;
- if(is_init) delay(200);
- //if(!is_init)delay(1);
- }
- unsigned char read()// 读取一个字节SD卡
- {
- DATEOUT=1;
- SCLK=1;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- dat_7=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- //if(!is_init)delay(1);
- dat_6=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_5=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_4=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_3=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_2=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_1=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- SCLK=0;
- if(is_init)delay(200);
- // if(!is_init)delay(1);
- dat_0=DATEOUT;
- return (dat);
- }
- //****************************
- void write1(unsigned char wr_)// 写入一个字节SD卡
- {
- dat=wr_;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1;
-
-
- }
- unsigned char read1()// 读取一个字节SD卡
- {
- DATEOUT=1;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
- //if(!is_init)delay(1);
- dat_7=DATEOUT;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
-
- //if(!is_init)delay(1);
- dat_6=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_5=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_4=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_3=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_2=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_1=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_0=DATEOUT;
- return (dat);
- }
- //******************************8
- void restsd()//复位SD卡
- { uchar i;
- uchar pcmd[6]={0x40,0x00,0x00,0x00,0x00,0x95};
- is_init=1;
-
- CS=1;
- for(i=0;i<15;i++)
- {
- //120时钟
- write(0xff);
- }
-
-
- CS=1;
- write(0xff);//据说是提高兼容性
- CS=0;//片选开
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
- fhz=read();
- for(;;)
- {
- fhz=read();
- if(fhz==0x01)break;
-
-
- }
-
- CS=1;
- write(0xff);
- }
-
- void initsd()//初始化SD
- {
- //
- uchar pcmd[6]={0x41,0x00,0x00,0x00,0x00,0xff};//
- //
-
- CS=1;
- write(0xff);//据说是提高兼容性
- CS=0;//片选开
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
-
-
- fhz=read();
- for(;;)
- {
- fhz=read();
- if(fhz==0x00)break;
-
-
- }
-
- CS=1;
- write(0xff);
-
-
-
- }
- void readsd(unsigned long addstart)//读SD卡物理一扇区的值送TAB表中
-
- {
- uint k,n;
- uchar zh1,zh2,zh3,zh4;
- uchar *p;
-
-
- p=&addstart; //取出存放Numb的地址的最高位!详细请看汇编!!
- zh1=*p; //这里必须要写!要不然就会出现播放开始正常,播到一定程度就乱了!因为他不一定位00!就是!!折腾我一天了!!!201012月31日搞定!
- p++; //由于最高位不用所以这里舍去小于2G
- zh2=*p;//从高到底的地第二字节 、、
- p++;
- zh3=*p; //从高到底的地第三字节
- p++;
- zh4=*p; //从高到底的地第四字节
- //readsd(numb);//读物理扇区
- //**************
- CS=0;//片选开
- write1( 0x51);
- write1( zh1);//这里是2G以下可以为00
- write1( zh2);
- write1( zh3);
- write1( zh4);
- write1( 0xff);
- DATEOUT=1;
-
- for(;;)
- {
- fhz=read1();
- if(fhz==0x00)break;
-
-
- }
- DATEOUT=1;
- for(;;)
- {
- fhz=read1();
- if(fhz==0xfe)break;
-
-
- }
- DATEOUT=1;
- n=0;
- for(k=512;k;k--)
- {
- tab[n]=read1();
- n++;
- }
- fhz=read1();
- fhz=read1();
- CS=1;
- write1(0xff);
-
-
-
- }
- void readsd_mp3(unsigned long numbs) //读一扇区的数据送MP3解码!!!
- {
- uchar *p;
- uchar zh2,zh3,zh4,zh1;
- uint j;
- p=&numbs; //取出存放Numb的地址的最高位!详细请看汇编!!
- zh1=*p;
- p++; //由于最高位不用所以这里舍去小于2G
- zh2=*p;//从高到底的地第二字节 、、
- p++;
- zh3=*p; //从高到底的地第三字节
- p++;
- zh4=*p; //从高到底的地第四字节
- //readsd(numb);//读物理扇区
- //**************
-
- XDCS=0;
- CS=0;//片选开
- dat=0x51;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1; //fhz=read1(); 以上是写SD卡
- //write1( 0x00);//这里是2G以下可以为00 //fhz=read1(); 以下是写SD卡
- dat=zh1;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1; //fhz=read1(); 以上是写SD卡
- //write1( zh2); //fhz=read1(); 以下是写SD卡
- dat=zh2;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1; //fhz=read1(); 以上是写SD卡
- // write1( zh3); //fhz=read1(); 以下是写SD卡
- dat=zh3;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1; //fhz=read1(); 以上是写SD卡
- //write1( zh4); //fhz=read1(); 以下是写SD卡
- dat=zh4;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1; //fhz=read1(); 以上是写SD卡
- // write1( 0xff); //fhz=read1(); 以下是写SD卡
- dat=0xff;
- DATEIN=dat_7;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
-
- DATEIN=dat_6;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_5;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_4;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_3;
-
- SCLK=0;
-
- SCLK=1;
-
-
- DATEIN=dat_2;
-
- SCLK=0;
-
-
- SCLK=1;
-
-
- DATEIN=dat_1;
-
- SCLK=0;
-
- SCLK=1;
-
- DATEIN=dat_0;
-
- SCLK=0;
-
- SCLK=1;
- DATEOUT=1; // 以上是写SD卡
-
- for(;;)
- {
- //fhz=read1(); 以下是读SD卡
- DATEOUT=1;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
- //if(!is_init)delay(1);
- dat_7=DATEOUT;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
-
- //if(!is_init)delay(1);
- dat_6=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_5=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_4=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_3=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_2=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_1=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_0=DATEOUT;
- fhz=dat; // 以上是读SD卡
- if(fhz==0x00)break;
-
-
- }
- DATEOUT=1;
- for(;;)
- {
- // fhz=read1(); 以下是读SD卡
- DATEOUT=1;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
- //if(!is_init)delay(1);
- dat_7=DATEOUT;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
-
- //if(!is_init)delay(1);
- dat_6=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_5=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_4=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_3=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_2=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_1=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_0=DATEOUT;
- fhz=dat; //fhz=read1(); 以上是读SD卡
- if(fhz==0xfe)break;
-
-
- }
- DATEOUT=1;
- // n=0;
- for(j=512;j;j--)
- {
- DATEOUT=1; //fhz=read1(); 以下是读SD卡
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
- //if(!is_init)delay(1);
- dat_7=DATEOUT;
- SCLK=1;
- //if(!is_init)delay(1);
- SCLK=0;
-
- //if(!is_init)delay(1);
- dat_6=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_5=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_4=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_3=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_2=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_1=DATEOUT;
- SCLK=1;
-
- // if(!is_init)delay(1);
- SCLK=0;
-
- // if(!is_init)delay(1);
- dat_0=DATEOUT; //fhz=read1(); 以上是读SD卡
- datmp3=dat; //fhz=read1(); 以下是写mp3bit流
- DREQ=1;
- while(!DREQ);
-
- SI=datmp3_7;
- //为了进一步提高速度我这里采用了顺序结构!全是断桥残雪惹的祸!第一次爱的人播放正常!而断桥残雪不行了!一定尽全力
- SCK=0; //从SD读取和MP3写数据流下手
- SCK=1;
-
- SI=datmp3_6;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_5;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_4;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_3;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_2;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_1;
-
- SCK=0;
- SCK=1;
-
- SI=datmp3_0;
-
- SCK=0;
- SCK=1;
-
-
-
-
-
-
-
- //以上是写mp3bit流
- }
- //**********************以下是读CRC*****
- DATEOUT=1;
- SCLK=1;
- SCLK=0;
- dat_7=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_6=DATEOUT;
- SCLK=1;
-
- SCLK=0;
-
- dat_5=DATEOUT;
- SCLK=1;
-
- SCLK=0;
-
- dat_4=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_3=DATEOUT;
- SCLK=1;
-
- SCLK=0;
- dat_2=DATEOUT;
- SCLK=1;
-
- SCLK=0;
-
- dat_1=DATEOUT;
- SCLK=1;
- SCLK=0;
- dat_0=DATEOUT;
- DATEOUT=1;
- SCLK=1;
- SCLK=0;
- dat_7=DATEOUT;
- SCLK=1;
- SCLK=0;
- dat_6=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_5=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_4=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_3=DATEOUT;
- SCLK=1;
- SCLK=0;
-
- dat_2=DATEOUT;
- SCLK=1;
- SCLK=0;
- dat_1=DATEOUT;
- SCLK=1;
- SCLK=0;
- dat_0=DATEOUT;
- CS=1;
- dat=0xff;
- DATEIN=dat_7;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_6;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_5;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_4;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_3;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_2;
- SCLK=0;
- SCLK=1;
- DATEIN=dat_1;
- SCLK=0;
- SCLK=1;
-
- DATEIN=dat_0;
- SCLK=0;
- SCLK=1;
-
- XDCS=1;
- //**********************以上是读CRC***** //**************
- }
-
- ////***************************************以上是SD主程序
- /*
- FAT32文件系统是用来寻找歌曲文件的手段!必须的 ////////////////////////////////////////////////////////////////////////////////////////////////////
- 下面是了
- 名称:FAT32 文件系统
- 说明:不要认为FAT32多神秘,其实他就是"查字典" 只是每一个环节都不能错!!!一环扣一环
- 编制:王均伟
- 地点:天津市开发区泰达地下交通空间第四项目部宿舍
- 时间:2010年12月29日19:00完成!调试完毕!!所有歌曲完整无缺的再现!
- 记:本文件系统是以簇为单位,也就是说要读就是一簇!不存在精确到扇区的算法!因此在切换
- 歌曲时容易出现几毫秒的等待或噪音!只读 了根目录的第一个扇区,所以不能播放超过第一扇区
- 存放的P3文件!也是经一步改进的地方!但是相对此系统而言,就简单了!我总结了!只要你有思路
- 你有想法!那么不管是否可行根据这个想法画出流程图,一步一步改进细化流程图,然后把流程分成几个
- 功能块!分别编写子函数,最后连起来!调试!关键是调试,一编编,一个问题要问:为什么会这样?是什么原因
- 导致的?一步步排查!实验,排查!一定能找到阻碍你的那块石头!!!
- */
-
- /*****************************************************************
- /* 函数名:unsigned long find_sd_type(); *
- /* 作用:FAT32系统中用来寻找根目录中的MP3文件 *
- /* 输入:无 *
- /* 输出:返回一个长整形作为找到的MP3文件的簇号 *
- /* *
- /* *
- /* *
- /* *
- /*****************************************************************
- */
- unsigned long find_sd_type()
- {
-
- uchar i,n,a,m,clr;
- unsigned long h1,h2,h3,h4,startadd;
-
- lpp: readsd(k);//这里的K一定要是全局变量!因为在函数调用时,他要不能变化 当然静态也是可以的!我觉得不保险,算了,加点内存加点吧
- switch (some)//some是用来扫描mp3文件!!!
- { case 0: {some=1; i=0;break; }//检测第0行,提供指针
- case 1: {some=2; i=2;break; }//检测第2行,提供指针
- case 2: {some=3; i=4;break; }//检测第4行,提供指针
- case 3: {some=4; i=6;break; }//检测第6行,提供指针
- case 4: {some=5; i=8;break; }//检测第8行,提供指针
- case 5: {some=6; i=10;break;}//检测第10行,提供指针
- case 6: {some=7; i=12;break;}//检测第12行,提供指针
- case 7: {some=8; i=14;break;}//检测第14行,提供指针
- case 8: {some=9; i=16;break;}//检测第16行,提供指针
- case 9: {some=10; i=18;break;}//检测第18行,提供指针
- case 10:{some=11; i=20;break;}//检测第20行,提供指针
- case 11:{some=12; i=22;break;}//检测第22行,提供指针
- case 12:{some=13; i=24;break;}//检测第24行,提供指针
- case 13:{some=14; i=26;break;}//检测第26行,提供指针
- case 14:{some=15; i=28;break;}//检测第28行,提供指针
- case 15:{some=0; i=30;break;}//检测第30行,提供指针
- }
-
- //把根目录中的第一扇区数据读入tab中!!!
- for(;;)
- {
- n=tab[8+(16*i)];//
- a=tab[9+(16*i)];//
- m=tab[10+(16*i)];//
- clr=tab[(16*i)];
-
- if((n==0x4d)&(a==0x50)&(m==0x33)&(clr!=0xe5)){break;}//如果有mp3文件扩展名且m之前第8个字节不能是e5,因为e5表示已经删除的文件,的话退出,没有就一直找!
- if((n==0)&(m==0)&(a==0)&(clr==0)){k=4323840;goto lpp;} //如果读到0000000,表示下面没有MP3文件了
- if(i==30){k=(k+512);goto lpp;}//如果读到30表示一个扇区读完了只是30里面没东西话
-
- goto lpp;
-
- }
- if(i==30){k=(k+512);}//如果读到了30行表示一个扇区读完了只是30行里有歌曲文件 这里的30表示一个扇区有0-31行:::
-
-
-
-
-
- //注意这里的i--;是必要的!应为我在比较后
- h1=tab[20+(16*i)]; //i多加了一次,所以要减去,因为下面我要用的!!就是这个原因!
- h2=tab[21+(16*i)];//查文件开始簇的地址
- h3=tab[26+(16*i)];
- h4=tab[27+(16*i)];//这里得到h1-h4表示
-
-
-
-
- h2=(h2<<24);//注意这里!h2是在32为中的32-24位 开始我在这里搞错了
- h1=(h1<<16);//注意这里!h1是在32为中的17-24位 ///格式转换!把它有逆序排列的十六进制转换成正常的高位在前的十六进制!!!
- h4=(h4<<8);//注意这里!h2是在32为中的8-16位 / /上面不用转换,文件名的排列是正确的!
- startadd=h1+h2+h3+h4;
-
- return(startadd);//返回文件的开始簇开始
- }
-
- /*****************************************************************
- /* 函数名:unsigned long find_sd_fat(unsigned long startadd1); *
- /* 作用:FAT32系统中用来查找FAT是否有下一簇的开始地址 *
- /* 如有则返回,没有则退出 *
- /* 输入:已经执行完的的或前一个簇号 *
- /* 输出:返回一个长整形作为找到的MP3文件的下一簇开始地址*
- /* *
- /* *
- /* *
- /* *
- /*****************************************************************
- */
- unsigned long find_sd_fat(unsigned long startadd1)
- {
- unsigned long a,b,c,d,startadd; //snumb存储扇区数
- static unsigned long snumb;
- snumb=((startadd1*4)/512);//占得扇区数
- readsd(2363904+(snumb*512));//读fat表放入tab中
- a=tab[(startadd1*4)-(snumb*512)];//最低字节
- b=tab[(startadd1*4)-(snumb*512)+1];
- c=tab[(startadd1*4)-(snumb*512)+2];
- d=tab[(startadd1*4)-(snumb*512)+3];//最高字节
- d=(d<<24);
- c=(c<<16);
- b=(b<<8);
- startadd=a+b+c+d;
- return (startadd);
- }
- ///////////////////////////////////////////////////////////////
- void main() //主程序
- {
- uint ct;
- unsigned long numb,f,st;//numb是簇号,f是物理地址,st 中间变量
-
- init_mp3();//初始化MP3
- ////////////////
- is_init=1;
- restsd(); //复位SD卡
- initsd(); //初始化SD卡
- is_init=0;//提高始终频率
- ///////////////
- sing(100);//正选测试
- while(1)//主循环
- {
-
- // numb=//从4327936物理地址开始读歌曲!
- loop: p1_7=0;
- numb=find_sd_type();//计算mp3文件的开始簇,返回计算出的文件开始簇号!
- p1_7=1;
- while(1)
- {
-
-
- f=(4323840+((numb-2)*4096));// 将计算歌曲的开始簇地址转化成SD卡的物理地址
- st=f;//中间量ST保证一个个基准量,F则不行!因为F要加0X200时刻变化的!!而ST则是不变的!!
- for(;;) //读出一簇数据送往MP3;
- {
-
- readsd_mp3(f);//给他地址他就播放!!!当然是物理SD地址
-
- f=(f+0x200);//因为是一簇所以要读扇区后腰加一扇区的地址更新
-
- if(f==(st+4096))break; //如果是一簇播放完毕!那么要退出!寻找下一簇!怎么找?FAT表
- }
-
- numb=find_sd_fat(numb); //查FAT表!找到下一簇!
- if(numb==0x0fffffff)//文件播放完毕?完毕就转到下一首,没完继续查fat表
- {
- XDCS=0;
- for(ct=2048;ct;ct--)
- {
-
- write_date_mp3(0);
-
-
- }
- XDCS=1;
-
- goto loop;
-
-
- }// 是否播放完毕?检测到0X0FFFFFFF表示播放完毕!如果完毕则转到loop执行
-
- }
-
- }
-
-
- }
复制代码
|