標題:
51單片機MP3制作總結 TFT9325彩屏 含程序
[打印本頁]
作者:
hongniu
時間:
2015-6-23 16:34
標題:
51單片機MP3制作總結 TFT9325彩屏 含程序
本帖最后由 hongniu 于 2015-6-23 16:50 編輯
MP3在之前對我來說是一個很深奧,很高級的東西!感性的認識就是前年買的那個MP3。說起MP3不得不說LCD12864,他起得頭,自從做完12864顯示后,我目標瞄向了彩屏!黑白屏有啥意思!彩色的才好來!于是又做TFT9325彩屏!在做彩屏之前做了一件非常非常重要的事!因為彩屏不同于12864,12864顯示一整屏才要1024個字節(jié),而彩屏2.4寸則要他的150倍!這么大的數(shù)據(jù)量你放哪?是個問題吧!這個東西必須要常見,必須要小,必須要容量大!他是什么呢?--沒錯,就是日常生活中的手機里的那張所謂的內存卡(人家叫TF卡)!第一他常見,第二他小,第三容量大,基本上是1個G的!那個卡只有指甲蓋大!很方便,所有條件滿足!就是他了!開始看關于TF卡的資料,首先是文件系統(tǒng)!實話當時我頭都大了!啥叫文件系統(tǒng)?什么原理?存儲機制是什么?有哪些操作?答案沒有現(xiàn)成的!但是資料告訴我們只要堅持一定會找到!慢慢的磨啊磨!開始知道我要學的文件系統(tǒng)沒名字叫FAT32文件系統(tǒng)!開始了解內部邏輯扇區(qū)和MBR,BPB,根目錄,F(xiàn)AT表,數(shù)據(jù)鏈,簇,扇區(qū),通信機制,數(shù)據(jù)讀寫,命令/指令,可是光有這些還是不行,要試驗,要調試,失敗,失敗,失敗,連著一個星期的失敗換來了成功,知道有一天,我記得特別清楚我從TF卡中讀到了55AA,那代表了扇區(qū)的結束標志,可是期待的EB(邏輯0扇區(qū)標志)沒有出現(xiàn),又一次失落了,懷疑,我讀錯了?還是......。不懂了,第二天我做了個通信,把數(shù)據(jù)一次性的送往計算機,到數(shù)據(jù)送出的那一刻,我激動了,我明白了,原來我讀出的并不是邏輯0扇區(qū),而是物理0扇區(qū),以前的思想多磨可笑。≡俅位A上我成功的讀出邏輯0扇區(qū)!跟實際的一摸一樣,這意味這我可以對TF卡的在地址范圍內的任意一個地址扇區(qū)進行讀。F卡的底層已經(jīng)對我打開了!這時我放下TF卡,專攻彩屏液晶顯示器!又是失敗,失敗,失敗,失敗,兩個星期后我終于可以在彩屏的任意點顯示任意顏色!接下來是把TF卡和液晶連起來!把JPG的320240的圖像轉換成BMP的16位圖像,轉成BIN,存到TF卡中,找到數(shù)據(jù)地址,吧數(shù)據(jù)地址送到液晶,液晶取出數(shù)據(jù)以掃描方式顯示在屏幕上!讀完正好掃描完成!正好是一幅完整的圖像!當然速度是很慢的!因為CPU實在是不敢恭維啊!但是他做到了!接下來搞啥呢?-----MP3!數(shù)據(jù)的存儲還用TF卡,就憑我的程序水平肯定編不出MP3解碼算法的,所以我決定使用專用的DSP解碼器,那我要做的是把數(shù)據(jù)給他!然后讓他解碼!DA后在耳機里聽到音樂!思路是有了!寫程序,修改,實驗,失敗,我目標很明確,任何器件都一樣,首先保證硬件是正確的,下一步是底層的驅動是成功的!因為解碼器用的通信使SPI,很容易實現(xiàn),一下午的功夫,搞定了!然后把數(shù)據(jù)送往MP3解碼器,此時在耳機里聽到悅耳的音樂!我真的很高興!因為這是有史以從未搞過的!接下來的幾天我開始遇到麻煩了!播放老是得我去計算歌曲的地址,然后告訴他,太麻煩,離顯示的MP3還太遙遠,于是開始著手改進,當我開始的時候問題來了,MP3的碼率不夠,導致有的比特流高的歌曲不能播放!又改程序,簡化代碼,提高速度,這里說一點,指針我頭一次用,效率果然不同一般!賊快!碼率解決了,怎樣讓他自己自動的找歌!而不用我人為地計算呢?-----呵呵-----文件系統(tǒng)!---我把我找個歌曲文件的方法換成代碼,就是了!程序一運行,感覺一切正常,自動找到歌曲并播放,問題又來了,放著放著亂了,本來是1的卻播到2去了!又開始找了一天的原因,第二天才知道原來少了一個變量,哎!曲折。∮謥韱栴}了,我明明在電腦上已經(jīng)刪除的文件他還在播!后來WNHEX才知道原來電腦刪除文件時在根目錄里吧文件名的第一個字節(jié)改成E5,哎呀,有是一頓修改,調試,終于昨天上午全部搞定!現(xiàn)在是一個通過手機TF卡或SD卡存儲4G文件為文件內存的,具FAT32文件系統(tǒng)、自動識別MP3文件、自動掃描歌曲目錄、自動順序播放、自動添加MP3文件的準MP3音樂播放器了。!當然離市面的MP3還差點,但是剩下的工作就是對系統(tǒng)的擴展了!什么音量調整了,進度條了,頻譜了,人機界面了!都可以在此基礎上做了。。
于天津開發(fā)區(qū)第四項目部。
源程序:
#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;//主-從數(shù)據(jù)輸入
sbit SCLK=P2^2;//時鐘信號
sbit DATEOUT=P2^3;//從-主數(shù)據(jù)輸出
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; //數(shù)據(jù)請求
sbit XDCS=P1^2; //數(shù)據(jù)片選
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寫入一個字節(jié),這里是最底層的數(shù)據(jù)發(fā)送!
{
datmp3=h;
SI=datmp3_7;
//為了進一步提高速度我這里采用了順序結構!全是斷橋殘雪惹的禍!第一次愛的人播放正常!而斷橋殘雪不行了!一定盡全力
SCK=0; //從SD讀取和MP3寫數(shù)據(jù)流下手
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讀取一個字節(jié)
{
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是數(shù)據(jù)注意這里是16位的數(shù)據(jù),內部做分開了處理
{
uchar h,l;
l=date;
h=(date>>8);
DREQ=1;
while(!DREQ); //檢測MP3模塊的忙狀態(tài)
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)//寫入音頻數(shù)據(jù)信息這里還有一點是XDCS在此函數(shù)外拉低
{
DREQ=1;
while(!DREQ);
datmp3=dat;
SI=datmp3_7;
//為了進一步提高速度我這里采用了順序結構!全是斷橋殘雪惹的禍!第一次愛的人播放正常!而斷橋殘雪不行了!一定盡全力
SCK=0; //從SD讀取和MP3寫數(shù)據(jù)流下手
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;//數(shù)據(jù)片選
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卡子程序,無返回值,有參函數(shù),參數(shù)為要寫入DATEIN數(shù)據(jù)線的字節(jié)*/
void write(unsigned char wr_)// 寫入一個字節(jié)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()// 讀取一個字節(jié)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_)// 寫入一個字節(jié)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()// 讀取一個字節(jié)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);//據(jù)說是提高兼容性
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);//據(jù)說是提高兼容性
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卡物理一扇區(qū)的值送TAB表中
{
uint k,n;
uchar zh1,zh2,zh3,zh4;
uchar *p;
p=&addstart; //取出存放Numb的地址的最高位!詳細請看匯編!!
zh1=*p; //這里必須要寫!要不然就會出現(xiàn)播放開始正常,播到一定程度就亂了!因為他不一定位00!就是!折騰我一天了。!201012月31日搞定!
p++; //由于最高位不用所以這里舍去小于2G
zh2=*p;//從高到底的地第二字節(jié) 、、
p++;
zh3=*p; //從高到底的地第三字節(jié)
p++;
zh4=*p; //從高到底的地第四字節(jié)
//readsd(numb);//讀物理扇區(qū)
//**************
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) //讀一扇區(qū)的數(shù)據(jù)送MP3解碼!。
{
uchar *p;
uchar zh2,zh3,zh4,zh1;
uint j;
p=&numbs; //取出存放Numb的地址的最高位!詳細請看匯編!
zh1=*p;
p++; //由于最高位不用所以這里舍去小于2G
zh2=*p;//從高到底的地第二字節(jié) 、、
p++;
zh3=*p; //從高到底的地第三字節(jié)
p++;
zh4=*p; //從高到底的地第四字節(jié)
//readsd(numb);//讀物理扇區(qū)
//**************
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寫數(shù)據(jù)流下手
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文件系統(tǒng)是用來尋找歌曲文件的手段!必須的 ////////////////////////////////////////////////////////////////////////////////////////////////////
下面是了
名稱:FAT32 文件系統(tǒng)
說明:不要認為FAT32多神秘,其實他就是"查字典" 只是每一個環(huán)節(jié)都不能錯。!一環(huán)扣一環(huán)
編制:王均偉
地點:天津市開發(fā)區(qū)泰達地下交通空間第四項目部宿舍
時間:2010年12月29日19:00完成!調試完畢!所有歌曲完整無缺的再現(xiàn)!
記:本文件系統(tǒng)是以簇為單位,也就是說要讀就是一簇!不存在精確到扇區(qū)的算法!因此在切換
歌曲時容易出現(xiàn)幾毫秒的等待或噪音!只讀 了根目錄的第一個扇區(qū),所以不能播放超過第一扇區(qū)
存放的P3文件!也是經(jīng)一步改進的地方!但是相對此系統(tǒng)而言,就簡單了!我總結了!只要你有思路
你有想法!那么不管是否可行根據(jù)這個想法畫出流程圖,一步一步改進細化流程圖,然后把流程分成幾個
功能塊!分別編寫子函數(shù),最后連起來!調試!關鍵是調試,一編編,一個問題要問:為什么會這樣?是什么原因
導致的?一步步排查!實驗,排查!一定能找到阻礙你的那塊石頭。。
*/
/*****************************************************************
/* 函數(shù)名:unsigned long find_sd_type(); *
/* 作用:FAT32系統(tǒng)中用來尋找根目錄中的MP3文件 *
/* 輸入:無 *
/* 輸出:返回一個長整形作為找到的MP3文件的簇號 *
/* *
/* *
/* *
/* *
/*****************************************************************
*/
unsigned long find_sd_type()
{
uchar i,n,a,m,clr;
unsigned long h1,h2,h3,h4,startadd;
lpp: readsd(k);//這里的K一定要是全局變量!因為在函數(shù)調用時,他要不能變化 當然靜態(tài)也是可以的!我覺得不保險,算了,加點內存加點吧
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行,提供指針
}
//把根目錄中的第一扇區(qū)數(shù)據(jù)讀入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個字節(jié)不能是e5,因為e5表示已經(jīng)刪除的文件,的話退出,沒有就一直找!
if((n==0)&(m==0)&(a==0)&(clr==0)){k=4323840;goto lpp;} //如果讀到0000000,表示下面沒有MP3文件了
if(i==30){k=(k+512);goto lpp;}//如果讀到30表示一個扇區(qū)讀完了只是30里面沒東西話
goto lpp;
}
if(i==30){k=(k+512);}//如果讀到了30行表示一個扇區(qū)讀完了只是30行里有歌曲文件 這里的30表示一個扇區(qū)有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);//返回文件的開始簇開始
}
/*****************************************************************
/* 函數(shù)名:unsigned long find_sd_fat(unsigned long startadd1); *
/* 作用:FAT32系統(tǒng)中用來查找FAT是否有下一簇的開始地址 *
/* 如有則返回,沒有則退出 *
/* 輸入:已經(jīng)執(zhí)行完的的或前一個簇號 *
/* 輸出:返回一個長整形作為找到的MP3文件的下一簇開始地址*
/* *
/* *
/* *
/* *
/*****************************************************************
*/
unsigned long find_sd_fat(unsigned long startadd1)
{
unsigned long a,b,c,d,startadd; //snumb存儲扇區(qū)數(shù)
static unsigned long snumb;
snumb=((startadd1*4)/512);//占得扇區(qū)數(shù)
readsd(2363904+(snumb*512));//讀fat表放入tab中
a=tab[(startadd1*4)-(snumb*512)];//最低字節(jié)
b=tab[(startadd1*4)-(snumb*512)+1];
c=tab[(startadd1*4)-(snumb*512)+2];
d=tab[(startadd1*4)-(snumb*512)+3];//最高字節(jié)
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)//主循環(huán)
{
// 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(xiàn)則不行!因為F要加0X200時刻變化的!而ST則是不變的!
for(;;) //讀出一簇數(shù)據(jù)送往MP3;
{
readsd_mp3(f);//給他地址他就播放!!當然是物理SD地址
f=(f+0x200);//因為是一簇所以要讀扇區(qū)后腰加一扇區(qū)的地址更新
if(f==(st+4096))break; //如果是一簇播放完畢!那么要退出!尋找下一簇!怎么找?FAT表
}
numb=find_sd_fat(numb); //查FAT表!找到下一簇!
if(numb==0x0fffffff)//文件播放完畢?完畢就轉到下一首,沒完繼續(xù)查fat表
{
XDCS=0;
for(ct=2048;ct;ct--)
{
write_date_mp3(0);
}
XDCS=1;
goto loop;
}// 是否播放完畢?檢測到0X0FFFFFFF表示播放完畢!如果完畢則轉到loop執(zhí)行
}
}
}
復制代碼
作者:
邰夏留
時間:
2015-12-3 21:38
頂一個,這都沒人感興趣,不知道這么多新手都學什么去了 。。。。
本新手表示,就對這些感興趣。。。
作者:
紅塵有你
時間:
2015-12-4 13:24
這個東西,樓主花了不少心血,必須得贊一個。
作者:
lishusen68
時間:
2015-12-10 22:38
這代碼太長了,謝謝
作者:
wc86110
時間:
2015-12-11 21:30
高工,給個代碼不解饞啊,出個 sch 或者來個DSN就更好了,大伙的資歷還沒達到能看懂你給出這復雜東西啊!
作者:
數(shù)遍繁星
時間:
2016-3-31 15:33
謝謝分享您幫了我大忙
作者:
nome2016
時間:
2016-4-3 01:59
感謝分享收藏下來慢慢嚼
作者:
沫離沫離
時間:
2016-4-4 13:39
這個東西,樓主花了不少心血,必須得贊一個!
作者:
騰飛的龍
時間:
2016-4-4 18:55
樓主辛苦,值得尊敬,謝謝分享。頂起。。。。。!
作者:
haogeV5
時間:
2016-5-19 21:55
樓主的精神值得學習!
作者:
1959744028
時間:
2016-5-27 10:07
對我來說這個太高端了.
作者:
hjsbs
時間:
2016-5-29 10:16
給個DSN 和hex就完美了
作者:
hxk9608
時間:
2016-7-26 14:35
樓主真花了不少心血啊,必須贊一個
作者:
fbzsn
時間:
2016-12-14 20:48
寫得好!注釋也詳細,值得初學者學習,樓主辛苦了,論壇有更精彩!
作者:
你就是個哈兒
時間:
2016-12-15 09:47
太厲害了哈!樓主 分享的東西,質量很高哈
作者:
黑黑—坤
時間:
2016-12-15 16:55
感謝樓主分享!
作者:
qin339599454
時間:
2017-1-9 12:46
很給力!
作者:
light-s
時間:
2017-2-22 22:04
非常有用
作者:
aa1151953633
時間:
2017-3-14 10:08
原理圖沒有啊?
作者:
dzbj
時間:
2017-3-14 14:04
佩服你的鉆研精神 希望能和你成為朋友 我也新人 分不多 捐2分意思意思 呵呵
作者:
不善言辭
時間:
2017-4-4 21:44
畢業(yè)設計要做這個,看了樓主寫的,收獲很大!
不知樓主可否發(fā)一下硬件原理圖。
作者:
YQS
時間:
2017-4-12 11:37
樓主真花了不少心血啊,必須贊一個,值得學習。
不過最好能共享原理圖,我等水平不夠,很難完全看懂程序,謝謝!
作者:
linnyshow
時間:
2017-8-6 09:05
厲害了。。。。
作者:
xhbert
時間:
2018-7-29 04:10
很厲害,佩服!
作者:
shwghsy
時間:
2019-7-11 06:50
這個帖子真不能沉下去,樓主的資料對新手來說是很大的幫助!沒看懂,沒關系多看幾次會有更多收獲!
作者:
千與千尋9527
時間:
2019-11-8 12:46
勵志小說呀 厲害
作者:
1124952194
時間:
2020-10-24 15:39
沒驗證,就看的話,SPI讀數(shù)據(jù)的地方有毛病
作者:
lyggg
時間:
2020-12-8 19:21
對我很有幫助,可以自己動手做一下
作者:
2864589610
時間:
2021-1-28 16:47
加油廢了不少心血把
作者:
woojoon1981
時間:
2021-2-6 15:48
無私奉獻的精神值得我輩學習
作者:
大漠游民
時間:
2021-3-8 13:15
好東西,寫的很詳細,必須得贊一個。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1