单片AT89C2051 + SD卡 + 3310LCD = 音乐播放器
http://www.amobbs.com/thread-4503884-1-1.html
?
這個小玩意,采用 ATMEL 的傳統51MCU作主控制芯片,加上SD卡和顯示屏,就可以作簡單的音樂播放器了,雖然音質不怎么樣,不過作為DIY還是蠻有樂趣,希望大家喜歡。
沒有采用FAT文件系統,只是按扇區讀取SD卡,由于2051資源有限,改為4051有望可以操作FAT,但目前程序還在不斷完善中。
128byte怎樣讀取512byte的扇區數據?可以采用邊讀邊播放的方式,就能解決。音樂文件是32KHz取樣率的WAV文件,所以和HIFI就沾不上邊了。
程序是用C來編寫,以方便交流,資料整理中,完善后再上傳。
這是未經整理的程序,有點亂,湊合著看,有時間再進一步改進。
SD部分是修改于本壇的一個貼子
----------------------------------------------------------
添加部分注釋,提高可讀性
#include <reg51.h>#include <INTRINS.H>#include <MATH.H>#include "LCD_3310.H"#define uchar unsigned char#define uint unsigned int#define ulong unsigned long/************ 定義管腳 *************/ sbit DOUT = P3^0; //SD卡數據輸出 sbit CLK = P3^1; //SD卡時鐘輸入 sbit DIN = P3^2; //SD卡數據輸入 sbit CS = P3^3; //SD卡片選使能/************ 全局變量 ************/ uchar pbuf[64]; //數據緩沖區 uchar p; //播放緩沖區指針 uchar px; //頻譜顯示的X坐標 code ulong Track[17] = { //0x15000,0x58000 SD卡中各聲音文件的首址,以后打算把這些數據放在SD卡的特定配置文件中再讀入。0xd7800-0x8a00,0x76b800-0x8a00,0xedc000-0x8a00,0x1752800-0x8a00,0x1F08000-0x8a00,0x2569800-0x8a00,0x2EDB800-0x8a00,0x3480000-0x8a00,0x3BFA800-0x8a00,0x41EB000-0x8a00,0x48EF000-0x8a00,0x508A000-0x8a00,0x59AE800-0x8a00,0x60AF000-0x8a00,0x6878000-0x8a00,0x6DBE000-0x8a00,0x7525800-0x8a00,};/******* SD訪問錯誤碼的定義 *******/#define INIT_CMD0_ERROR 0X01#define INIT_CMD1_ERROR 0X02#define READ_BLOCK_ERROR 0X03#define WRITE_BLOCK_ERROR 0X04/********* 通用延時函數 ***********/ void delay(uint i){while(i--);}/******** SD寫入一個字節 **********/ void spi_write(uchar x){ //不采用循環結構是為了提高處理速度DIN = x & 0x80;CLK = 0;CLK = 1;DIN = x & 0x40;CLK = 0;CLK = 1;DIN = x & 0x20;CLK = 0;CLK = 1;DIN = x & 0x10;CLK = 0;CLK = 1;DIN = x & 0x08;CLK = 0;CLK = 1;DIN = x & 0x04;CLK = 0;CLK = 1;DIN = x & 0x02;CLK = 0;CLK = 1;DIN = x & 0x01;CLK = 0;CLK = 1;}/******* SD慢速寫入一個字節 ********/ void spi_write_low_speed(uchar x){uchar i;for(i = 8; i; --i){DIN = x & 0x80;x <<= 1;CLK = 0;delay(1);CLK = 1;delay(1);}}/*********** SD讀入一字節 ***********/ uchar spi_read(void){ //利用51串口的同步移位功能,以達了最高的讀度2MHz CLKRI = 0;while(RI == 0);return SBUF;}/******** SD慢速讀入一字節 **********/ uchar spi_read_low_speed(void){uchar temp,i;for(i = 8; i; --i){CLK = 0;delay(1);temp <<= 1;if(DOUT) temp++;CLK = 1;delay(1);}return temp;}/******** 發送一組SD命令 ************/ uchar write_cmd(uchar data *pcmd){uchar temp,time=0,i;for(i = 0; i<6; i++) //一條命令都是6個字節,形參用指針,{ //指向6個字節命令, spi_write(pcmd);}do //看看寫進去沒有,通過so管腳 {temp = spi_read();time++;} //一直到讀到的不是0xff或超時,退出去while(temp==0xff && time<100);return temp;}/****** 慢速發送一組SD命令 **********/ uchar write_cmd_low_speed(uchar *pcmd){uchar temp,time=0,i;for(i=0;i<6;i++) //一條命令都是6個字節,形參用指針,{ //指向6個字節命令, spi_write_low_speed(pcmd);}do //看看寫進去沒有,通過so管腳 {temp = spi_read_low_speed();time++;} //一直到讀到的不是0xff或超時,退出去while(temp==0xff && time<100);return temp;}/********* SD卡 激活,復位 *********/ uchar sd_reset(void){uchar time,temp,i;uchar pcmd[6]={0x40,0x00,0x00,0x00,0x00,0x95};CS = 1;for(i = 0; i < 0x0f; i++) //復位時,至少要72個時鐘周期,{ //現在是,15*8=120個clkspi_write_low_speed(0xff);}CS = 0;time=0;do{temp = write_cmd_low_speed(pcmd);time++;if(time > 100) return INIT_CMD0_ERROR;}while(temp != 0x01); //校驗碼是0x01,表示寫入成功CS = 1;spi_write_low_speed(0xff);//時序上要求補8個clkreturn 0; //返回0,寫入成功 }/************ SD卡初始化 ************/ uchar sd_init(void){uchar time, temp;uchar pcmd[6] = {0x41,0x00,0x00,0x00,0x00,0xff};CS = 0;time = 0;do{temp = write_cmd_low_speed(pcmd);time++;if(time > 100) return INIT_CMD1_ERROR;} while(temp != 0x00);CS = 1;spi_write_low_speed(0xff);return 0;}/******* 讀取一扇區的點陣圖像 *********/ uchar sd_read_bmp(uchar data *ad){uchar temp, time, x, pcmd[6];uint j = 0;pcmd[0] = 0x51;pcmd[1] = *ad;pcmd[2] = *(++ad);pcmd[3] = *(++ad);pcmd[4] = 0;pcmd[5] = 0xff;CS = 0;time = 0;do{temp = write_cmd(pcmd);if(++time > 100){CS = 1;return READ_BLOCK_ERROR;}}while(temp != 0);//等待SD卡回應while(spi_read() != 0x7f); //0xfe,51的串口移位是LSB優先,所以結果高低位倒置for (j = 0; j < 504; j++) //3310的分辨率為 84 * 48,總計用504字節 {LCD3310_write_dat(spi_read());}for (x = 0; x < 10; x++) spi_read(); //略過8字節數據和2字節CRCspi_write(0xff);CS = 1;return 0;}/******* 讀取一扇區的聲音數據 *********/ uchar sd_read_sector(uchar data *ad){uchar temp, time, pcmd[6];uint j = 0;pcmd[0] = 0x51;pcmd[1] = *ad;pcmd[2] = *(++ad);pcmd[3] = *(++ad);pcmd[4] = 0;pcmd[5] = 0xff;CS = 0;time = 0;do{temp = write_cmd(pcmd);if(++time > 100){CS = 1;return READ_BLOCK_ERROR;}}while(temp != 0);//等待SD回應的時間有點長,所以在這里插入顯示模擬的頻譜圖temp = pbuf[16]; //隨便挑一個數據顯示LCD3310_set_XY(px,5); //設定顯示位置px += 6;if (px >= 39) px = 0;if (temp & 0x80) temp ^= 0x80; //求得聲音振幅else temp = 0x80 - temp;temp = Level[temp>>4]; //不同幅度對應不同的譜線圖案 LCD3310_write_dat(temp);LCD3310_write_dat(temp);LCD3310_write_dat(temp);while(spi_read() != 0x7f);//0xfe,51的串口移位是LSB優先,所以結果高低位倒置while(1) //讀取512字節數據 {RI = 0;_nop_(); pbuf[j++ & 63] = SBUF; //為求快速,不用函數調用RI = 0;_nop_(); pbuf[j++ & 63] = SBUF; //直接啟動串口移入RI = 0;_nop_(); pbuf[j++ & 63] = SBUF; //連續讀四字節RI = 0;_nop_(); pbuf[j++ & 63] = SBUF;if(j >= 512) break;while((((uchar)j - p) & 63) > 55); //檢測播放進度,} //如果緩沖區接近溢出,先暫停等待spi_read();//略過 crcspi_read();//略過 crcspi_write(0xff);//SD 時序要求補8個脈沖CS = 1;return 0;}/**************************** 主程序 *******************************/ int main(void){uchar key,n,Count,Min,Sec;ulong addr; // SD 的扇區地址 P1 = 0x80; // DAC 輸出中點電壓RI = 1;REN = 1;TMOD = 0x02;TH0 = 256 - 62.5; //定時器設定約為 32KHz,和WAV文件取樣率對應ET0 = 1;EA = 1;px = 0;n = 64;do pbuf[--n] = 0x80; while(n); //填充播放緩沖區delay(65535);LCD3310_init();LCD3310_set_XY(0,0);LCD3310_write_cmd(0x22); //設定LCD掃描順序 sd_reset();sd_init();addr = 0x4f400;sd_read_bmp((uchar) &addr); //顯示歡迎畫面while (D_C == 1) ;while (D_C == 0) ; //等待按鍵delay(65535);//============== main loop ==================while(1) //循環播放所有曲目 {TR0 = 0;LCD3310_write_cmd(0x22);LCD3310_set_XY(0,0);addr = 0x4f600 + ((uint)n<<9);sd_read_bmp((uchar) &addr); //顯示歌名、歌手LCD3310_write_cmd(0x20);TR0 = 1;p = 0xd0;Min = 0;Sec = 0;Count= 0;for (addr = Track[n]; addr < Track[n+1];)//播放第n曲 {//============ 按鍵處理 ===============key = (key >> 2) | (P3 & 0x30); //僅一句的掃鍵函數,包括掃描和消抖if (key == 0x03) //鍵碼為03是播放/暫停鍵 {LCD3310_set_XY(78,5);TCON ^= 0x10; //TR0 取反if (TR0) LCD3310_print(11); //顯示播放符號else LCD3310_print(12); //顯示暫停符號 } else if (key == 0x2b) //鍵碼為2b是前一曲 {if ((Min || (Sec & 0xf0))) n--;//10秒后跳本曲開始else n -= 2; //10秒內跳前一曲break;}else if (key == 0x17) //鍵碼為17是后一曲break;//======== 讀一扇區數據或暫停 =========if (TR0 == 0) {delay(2000); continue;}sd_read_sector((uchar) &addr);addr += 512;//=========== 播放時間計數 ============Count += 2;if (Count >= 125){Count -= 125;Sec++;if ((Sec & 0x0f) > 9){Sec += 6;if (Sec >= 0x60){Sec = 0;Min++;if ((Min & 0x0f) > 9){Min += 6;if (Min > 0x60) Min = 0;}}}}//======= 分時間片顯示時間/標志 ========switch (Count & 14){case 2: LCD3310_set_XY(44,5);LCD3310_print(Min>>4);//分鐘十位break;case 4: LCD3310_set_XY(50,5);LCD3310_print(Min&15);//分鐘個位break;case 6: LCD3310_set_XY(56,5);LCD3310_print(10); //分隔符break;case 8: LCD3310_set_XY(62,5);LCD3310_print(Sec>>4);//秒十位break;case 10: LCD3310_set_XY(68,5);LCD3310_print(Sec&15);//秒個位break;case 12:LCD3310_set_XY(78,5);if (Count & 0x40) LCD3310_print(13); //閃動播放符號else LCD3310_print(11); }}n++; //下一曲n &= 15; //這個SD卡只有16首歌}//while(1);}//main()void timer0 (void) interrupt 1 using 1{if (TL0 & 1) _nop_(); //消除中斷響應時間不一致,造成的頻率抖動P1 = pbuf[++p & 63]; //輸出一個聲音數據 }
這是3310 LCD 部分
#include <reg51.h>#include <INTRINS.H>sbit SDIN = P3^2; //P3^2sbit SCLK = P3^4;sbit D_C = P3^5;sbit SCE = P3^7;code unsigned char Font[70] = {0x3E, 0x51, 0x49, 0x45, 0x3E , // 00x00, 0x42, 0x7F, 0x40, 0x00 , // 10x42, 0x61, 0x51, 0x49, 0x46 , // 20x21, 0x41, 0x45, 0x4B, 0x31 , // 30x18, 0x14, 0x12, 0x7F, 0x10 , // 40x27, 0x45, 0x45, 0x45, 0x39 , // 50x3C, 0x4A, 0x49, 0x49, 0x30 , // 60x01, 0x71, 0x09, 0x05, 0x03 , // 70x36, 0x49, 0x49, 0x49, 0x36 , // 80x06, 0x49, 0x49, 0x29, 0x1E , // 90x00, 0x00, 0x36, 0x36, 0x00 , // :0x7f, 0x3e, 0x1c, 0x08, 0x00 , // >0x3e, 0x3e, 0x00, 0x3e, 0x3e , // ||0x00, 0x00, 0x00, 0x00, 0x00 , //" " }; code unsigned char Level[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,};extern void delay(unsigned int i);void LCD3310_write_cmd(unsigned char cmd){D_C = 0;SCLK = 0;SCE = 0;delay(3);SDIN = cmd & 0x80;SCLK = 1;SDIN = cmd & 0x40;SCLK = 0;SCLK = 1;SDIN = cmd & 0x20;SCLK = 0;SCLK = 1;SDIN = cmd & 0x10;SCLK = 0;SCLK = 1;SDIN = cmd & 0x08;SCLK = 0;SCLK = 1;SDIN = cmd & 0x04;SCLK = 0;SCLK = 1;SDIN = cmd & 0x02;SCLK = 0;SCLK = 1;SDIN = cmd & 0x01;SCLK = 0;SCLK = 1;D_C = 1;SDIN = 1;SCE = 1;}void LCD3310_write_dat(unsigned char dat){// D_C = 1;SCLK = 0;SCE = 0;delay(3);SDIN = dat & 0x80;SCLK = 1;SDIN = dat & 0x40;SCLK = 0;SCLK = 1;SDIN = dat & 0x20;SCLK = 0;SCLK = 1;SDIN = dat & 0x10;SCLK = 0;SCLK = 1;SDIN = dat & 0x08;SCLK = 0;SCLK = 1;SDIN = dat & 0x04;SCLK = 0;SCLK = 1;SDIN = dat & 0x02;SCLK = 0;SCLK = 1;SDIN = dat & 0x01;SCLK = 0;SCLK = 1;D_C = 1;SDIN = 1;SCE = 1;}void LCD3310_init(void){LCD3310_write_cmd(0x21);LCD3310_write_cmd(0xd7);LCD3310_write_cmd(0x06);LCD3310_write_cmd(0x20);LCD3310_write_cmd(0x0c);}void LCD3310_set_XY(unsigned char x,unsigned char y){if (x >= 84) return;if (y >= 6) return;LCD3310_write_cmd(0x80 | x);LCD3310_write_cmd(0x40 | y);}void LCD3310_print(unsigned char n){n = (n << 2) + n;LCD3310_write_dat(Font[n]);LCD3310_write_dat(Font[++n]);LCD3310_write_dat(Font[++n]);LCD3310_write_dat(Font[++n]);LCD3310_write_dat(Font[++n]);}
?回復【104樓】maxims
呵呵,希望能解釋一下電路
-----------------------------------------------------------------------
R1、C1 組成LCD的上電復位電路。
R2~R4是上拉電阻,雖然2051的IO有內部的弱上拉,但這三個IO是LCD接口與鍵盤接口復用,需要上拉強一點。
R5、R6、Q1組成OC輸出的反相器,當SCE為高電平時,三極管導通,鍵盤使能,LCD通信中止;當SCE為低電平時,LCD通信使能,鍵盤斷開。需要注意的是圖中左右兩鍵沒加隔離二極管,不要同時按下,否則引起顯示錯亂。
R2~R6的參數不要大幅度改動,這些參數是經過計算得到一個比較合適的值。
晶振、C3、C5沒什么好說,這些都單片機系統必需的。
R7、R8是P1.0和P1.1的上拉電阻,因為這兩個口是開漏輸出。
R9~R24組成R2R型DAC,選取50K/100K是因為2051輸出高電平的帶載能力差,電阻太小將導致DAC線性變差。這里的電阻最好用1%的金屬膜電阻,以改善DAC的線性度。50K電阻是非標電阻,這里用51K和2.7M電阻并聯代替。
C6是高頻濾波電容,以減少DAC輸出的高頻噪聲。
C7是輸出耦合電容,連接LINE OUT輸出端子,輸出阻抗較高,50K,只能接功放機或有源音箱。如果接耳機,需加一級放大,可以用運放做跟隨器,或用TDA2822功放IC,能帶個小嗽叭。
?
回復【105樓】jeep
//由于部分顯示數據在sd卡中,所以sd卡需要存入一個特別的文件//
那個是特別文件還不明白你的意思
-----------------------------------------------------------------------
回復【108樓】wsm80828
很想知道這個
//由于部分顯示數據在sd卡中,所以sd卡需要存入一個特別的文件//??
-----------------------------------------------------------------------
是一個存放歌曲名稱、歌手名稱、歌曲首址和長度的文件,2051只有2K ROM,不可能把整個中文字庫存進ROM內,只能存在SD卡中,以圖片形式存貯,需要時讀入。哪位能用VB或VC做一個轉換工具自動生成一個playlist.dat就方便了。
?
?
U32 GetRootDir(void)
{
? ? ? ? U32 root, fat1, fat2;
? ? ? ? MMCRdBolckOne(0x00,Buffer);? ?? ?// 讀取SD卡中的數據
? ? ? ?
? ? ? ? fat1 = ((Buffer[0x0f]<<8) | Buffer[0x0e]) * 512;
? ? fat2 = ((Buffer[0x25]<<8) | Buffer[0x24]) * 512 + fat1;
? ? ? ? root = ((Buffer[0x25]<<8) | Buffer[0x24]) * 512 + fat2;
? ? ? ?
? ? ? ? return root;
}
這里是使用512的緩存,可以修改成樓主的64緩存,只要讀取出第 0x0e,0x0f, 0x25,0x24地址的數據就可以計算了
用于查找根目錄的函數,那樣就可以查找歌曲了
根目錄 每32個數據表示一個文件,分辨出WAV格式的文件 找到相應的簇地址,然后進行播放
?
?
馬老師你好,對于你所提及的問題,在我轉換過的聲音文件中也有同樣體現。究其原因,主要是8BIT取樣深度不夠,聲音電平在接近零點時,由于隨機噪聲的影響,導致取樣值在0x80,0x79,0x81這間變化,以產生噪聲。我認為這種噪聲一直都存在,只是其它聲音較大時掩蔽了而矣。
? ? 解決方法,可參考類似杜比動態降噪技術,作這樣的處理:檢測當前聲音幅度,如果在持續的一段時間內(比如0.2秒)聲音幅度小于一定值(比如0x80 正負1),那么都過濾為0x80,即可解決此問題。
? ? 我記得有些音頻處理軟件可以進行這種變換,我回去找找。即使沒有,編個小程序轉一下也不難。
?
聽過【149樓】所提供的8BIT聲音樣本,發現其噪聲很大,估計所用的商業軟件在轉換算法上有問題。我用WINDOWS XP附件自帶的錄音機,打開原始16BIT聲音文件,然后另存為44KHz 8BIT,效果也比【149樓】的好得多。
?
回復【151樓】cowboy
聽過【149樓】所提供的8bit聲音樣本,發現其噪聲很大,估計所用的商業軟件在轉換算法上有問題。我用windows xp附件自帶的錄音機,打開原始16bit聲音文件,然后另存為44khz 8bit,效果也比【149樓】的好得多。
-----------------------------------------------------------------------
謝謝!
我使用過幾個商業軟件,如上圖中的AUDITION、天天靜聽等,都是如此。自己寫了一個轉換程序,就是直接簡單的采用除256的方法,直接把16位降成8位,這樣處理后,靜音部分可以完全轉換為靜音,而且總的噪聲比這些商業軟件小了許多(-3db左右),但是還有,還是可以比較清晰的聽到,尤其是當調節音量輸出比較大的時候。
我會試一下WINDOWNS的附件,聽聽效果。
現在手頭的項目,需要語音提示??紤]到存儲容量,使用8K、8位的WAV數據,應該可以達到電話的語音質量,對于一般應用夠了。其它都可以,成本也不高,就是轉換數據本聲的噪聲。想找一種簡單的處理辦法。
后面我還會繼續提供一些我使用過的處理辦法。
另外是否其它的朋友有這方面的經驗,軟件或算法,只要提供一個思路就可以了,先表示感謝。
?
/**********************************************************************************************/
點擊此處下載 ourdev_611680M0SOZB.rar(文件大小:2.32M) (原文件名:goldwave v5.23 漢化版.rar)
用這個轉換成8Bit單聲道PCM文件,效果很好。16Bit轉8Bit不會改變采樣頻率,故需先轉成32KHz的其它格式再轉成PCM
?
回復【154樓】machao
回復【151樓】cowboy??
聽過【149樓】所提供的8bit聲音樣本,發現其噪聲很大,估計所用的商業軟件在轉換算法上有問題。我用windows xp附件自帶的錄音機,打開原始16bit聲音文件,然后另存為44khz 8bit,效果也比【149樓】的好得多。
-----------------------------------------------------------------------
謝謝!
我使用過幾個商業軟件,如上圖中的audition、天天靜聽等,都是如此。自己寫了一個轉換程序,就是直接簡單的采用除256的方法,直接把16位降成8位,這樣處理后,靜音部分可以完全轉換為靜音,而且總的噪聲比這些商業軟件小了許多(-3db左右),但是還有,還是可以比較清晰的聽到,尤其是當調節音量輸出比較大的時候。
我會試一下windowns的附件,聽聽效果。
現在手頭的項目,......
-----------------------------------------------------------------------
馬老師我提個建議吧。我做過類似的項目,是用PWM直接接一功放驅動喇叭。沒有加低通濾波,當使用20K以下的采樣頻率WAV文件時有嘯聲,使用20K以上時人就聽不到了。這里應該是由PWM的高低電平跳動引起的,使用DA應該沒有類似問題。
所以我就沒有采用8K的采樣,而是使用24K采樣,8:2的ADPCM編碼方式。對比下文件大小:8KHz 8Bit的PCM格式64Kbps, 24KHz 8Bit ADPCM為 24*8/4 = 48Kbps,只有8K的3/4大小。而音質上壓縮的肯定比降低采樣頻率更好一些。
這里也有一個小問題,我使用這個軟件編8:4 ADPCM再解碼時有很大噪音,這里是因為其碼表可能與我用的不同。網上8bit的ADPCM基本上沒有,我是將16位的改成8位的,所以碼表是可能不同。我的解決辦法是自己編碼再自己解碼,8:2也能達到較好的效果,聽歌尚可,語音更不用說,用DA的話效果肯定更好,而加濾波的話有些音色會變。
?
播放BUF和讀取BUF我是分開的,開辟了兩個數據區A,B,這樣就不用讀一個播放一個。播放完BUF_A再播放BUF_B,同時BUF_A從FLASH中讀取相應數據,依此循環。
?
回復【159樓】amazing030
謝謝您了,我會用你建議的goldwave v5.23.rar試一下的。
壓縮編碼的方式我知道,做過圖象的壓縮,JPEG,H26x等。在這個項目上,不想使用這么復雜的東西。我設計是提供一個DS卡,和規定的文件名,然后給的PC程序給用戶。用戶自己需要什么語音自己在PC上做,然后轉換成8位的,考入SD卡就可以了。
另外,系統使用8位MCU,時鐘也就10M左右,還要做其它的事情,ADPCM解碼,還是不做的好。
另外,你的解釋是不對的。我提供的兩個文件與系統播放無關,就是在PC上轉換,然后在PC上播放,采樣率為44.1k。僅用PC轉換,在PC播放,沙沙的噪聲非常明顯。與什么PWM沒有關系。
?
解決數字音頻信號傳輸中劣化方式(http://www.av010.com/jswz_html/jswz2280_1.html)
專業的解釋,看來解決比較困難了。
/**********************************************************************************************/
回復【80樓】cowboy
-----------------------------------------------------------------------
小弟不才,
請問樓主
void timer0 (void) interrupt 1 using 1
{
? ? if (TL0 & 1) _nop_(); //消除中斷響應時間不一致,造成的頻率抖動
? ? P1??= pbuf[++p & 63]; //輸出一個聲音數據
}
這其中的" & 63"的作用是什么呢?
?
回復【167樓】hongfadg
-----------------------------------------------------------------------
p & 63 是取8位“p”中的低6位,舍棄高2位,由于緩沖區只有64字節,“++p & 63”正好循環指向pbuf[0]至pbuf[63]。
?
/**********************************************************************************************/
播放器升級預告,增加FAT32文件系統,也就是可以隨意增減音樂文件,不必按連續的儲存空間存放文件,允許有文件碎片,同時也不再需要在SD卡內存放一個經特殊制作系統文件。
硬件沒改變,只是軟件升級,雖然增加了FAT32部分代碼,但總代碼量仍在2K以內,89C2051能裝得下。
測試基本通過,整理好后再上傳。
上傳升級版的整套工程文件,以及SD內的示范文件。
點擊此處下載 ourdev_615881TB11F5.rar(文件大小:429K) (原文件名:SD_player.rar)
由于水平有限,程序可能還有很多不完善的地方,希望大家多提意見。特別是SD卡驅動和FAT32文件系統,本人理解并不深入,程序對各種SD卡的兼容性未作詳細測試,有可能出現某些SD卡不能播放的情況。對SD卡的基本要求是 文件系統為FAT32格式,暫不支持FAT16;SDHC高速卡也不支持。
/**********************************************************************************************/
轉載于:https://www.cnblogs.com/LittleTiger/p/3976672.html
總結
以上是生活随笔為你收集整理的单片AT89C2051 + SD卡 + 3310LCD = 音乐播放器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二手冰箱多少钱啊?
- 下一篇: 2014百度面试题目---“求比指定整数