第21章 MP3播放器實驗 1 電路圖 2 程序移植
0.png (226.99 KB, 下載次數: 144)
下載附件
2016-3-29 02:05 上傳
本章實現的功能是單片機讀取SD卡中的MP3音樂文件進行自動播放。 1 電路圖
1.png (55.06 KB, 下載次數: 165)
下載附件
2016-3-29 02:05 上傳
1號單片機與VS1003的接口電路
3.png (98.57 KB, 下載次數: 141)
下載附件
2016-3-29 02:05 上傳
程序中比較重要的代碼是VS1003的復位操作,每首歌曲播放完畢都需執行一次復位操作,否 則后面播放的音樂會出現模糊不清的問題,復位操作包括硬件復位與軟件復位。 void VS_Reset() { /////////// 硬件復位 ////////// unsigned char retry=0; VS_XDCS=1; // 取消數據傳輸 VS_XCS=1; // 取消指令傳輸 VS_XRESET=1; delay(10); VS_XRESET=0; // 硬件低電平復位 delay100mS(); // 延時100ms VS_XRESET=1; while(VS_DREQ==0&&retry<200) // 等待DREQ為高 { retry++; delay50us(); }; delay20ms(); /////////// 軟件復位 ////////// VS_Write_Reg(0x00,0x08,0x04); // 軟件復位,向模式寄存器寫入0x0804即可 /////////// 初始化 ////////// VS_Write_Reg(0x03,0x98,0x00); // 時鐘設置,3倍頻 VS_Write_Reg(0x0b,0x00,0x00); // 音量設置,左右聲道均最大音量 VS_XDCS=0; // 打開數據片選,注意此時XCS(片選)為高電平 SPI_WriteByte(0); // 寫入數據,這里寫入4個字節00或FF,是無關數據,用來啟動數據傳輸 SPI_WriteByte(0); SPI_WriteByte(0); SPI_WriteByte(0); VS_XDCS=1; // 關閉數據片選 if(retry>=200)return 1; // 硬件復位失敗 else return 0; // 硬件復位成功 }
部分程序預覽:
vs1003.c文件:
- #include "vs1003.h"
- #include "patch.h"
- #include "myfun.h"
- /****************《51單片機輕松入門-基于STC15W4K系列》配套例程 *************
- ★★★★★★★★★★★★★★★★★★★★★★★★
- 《51單片機輕松入門-基于STC15W4K系列》 一書已經由北航出版社正式出版發行。
- 作者親手創作的與教材配套的51雙核實驗板(2個MCU)對程序下載、調試、仿真方便,不需要外部
- 仿真器與編程器,這種設計方式徹底解決了系統中多個最高優先級誰也不能讓誰的中斷競爭問題。
- QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
- 驗證信息:STC15單片機
- 郵箱:xgliyouquan@126.com
- ★★★★★★★★★★★★★★★★★★★★★★★★*/
- unsigned char bdata dat; //dat是可位尋址的變量
- sbit dat7=dat^7;
- sbit dat6=dat^6;
- sbit dat5=dat^5;
- sbit dat4=dat^4;
- sbit dat3=dat^3;
- sbit dat2=dat^2;
- sbit dat1=dat^1;
- sbit dat0=dat^0; //取出dat的各個位
- /******************************************************************
- 功能:IO模擬SPI,發送一個字節
- ******************************************************************/
- void SPI_WriteByte(unsigned char x)
- {
- dat=x; // 將x的值賦給可位尋址的變量dat,以便取出各個位
-
- SPI_SI=dat7; // 取出第7個位,寫到數據線上
- SPI_SCLK=0;
- SPI_SCLK=1; // 時鐘線產生上升沿,數據被寫入
-
- SPI_SI=dat6;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat5;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat4;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat3;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat2;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat1;
- SPI_SCLK=0;
- SPI_SCLK=1;
-
- SPI_SI=dat0;
- SPI_SCLK=0;
- SPI_SCLK=1;
- }
- /******************************************************************
- 功能:IO模擬SPI,讀取一個字節
- ******************************************************************/
- //unsigned char SPI_ReadByte()
- //{
- // SPI_SO=1;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat7=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat6=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat5=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat4=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat3=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat2=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat1=SPI_SO;
- //
- // SPI_SCLK=1;
- // delay(1);
- // SPI_SCLK=0;
- // delay(1);
- // dat0=SPI_SO;
- //
- // return dat;
- //}
- /******************************************************************
- 功能:向VS1003的功能寄存器中寫入數據(兩個字節)
- 參數:addr是功能寄存器的地址
- hdat是要寫入的高字節
- ldat是要寫入的低字節
- ******************************************************************/
- void VS_Write_Reg(unsigned char addr,unsigned char hdat,unsigned char ldat)
- {
- VS_DREQ=1; // 51單片機IO作輸入時先置為1
- while(!VS_DREQ); // VS1003的DREQ為高電平時才接收數據
- VS_XCS=0; // 打開命令片選,這樣才能對功能寄存器進行讀寫
- SPI_WriteByte(0x02); // 寫入操作碼0x02 00000010 (功能寄存器寫操作)
- SPI_WriteByte(addr); // 寫入寄存器地址
- SPI_WriteByte(hdat); // 寫入高字節
- SPI_WriteByte(ldat); // 寫入低字節
- VS_XCS=1; // 關閉命令片選
- }
- /******************************************************************
- 功能:從VS1003的功能寄存器中讀取數據(2個字節)
- 參數:addr是功能寄存器的地址
- 返回:返回從VS1003的功能寄存器中讀到的值
- ******************************************************************/
- //unsigned int VS_Read_Reg(unsigned char addr)
- //{
- // unsigned int temp=0;
- // VS_DREQ=1; // 51單片機IO作輸入時先置為1
- // while(!VS_DREQ); // VS1003的DREQ為高電平時才接收數據
- // VS_XCS=0; // 打開命令片選,這樣才能對功能寄存器進行讀寫
- // SPI_WriteByte(0x03); // 讀出操作碼0x03 00000011(功能寄存器讀操作)
- // SPI_WriteByte(addr); // 寫入寄存器地址
- // temp=SPI_ReadByte(); // 讀高字節
- // temp<<=8;
- // temp|=SPI_ReadByte(); // 讀取低字節,與高字節拼成一個整數
- //
- // VS_XCS=1; // 關閉命令片選
- // return temp; // 返回讀到的值
- //}
- /******************************************************************
- 功能:VS1003硬件復位+軟件復位+初始化(設置時鐘頻率及音量)
- ******************************************************************/
- unsigned char VS_Reset()
- {
- /////////// 硬件復位 //////////
- unsigned char retry=0;
- VS_XDCS=1; // 取消數據傳輸
- VS_XCS=1; // 取消指令傳輸
- VS_XRESET=1;
- delay(10);
- VS_XRESET=0; // 硬件低電平復位
- delay100mS(); // 延時100ms
- VS_XRESET=1;
- while(VS_DREQ==0&&retry<200) //等待DREQ為高
- {
- retry++;
- delay50us();
- };
- delay20ms();
- /////////// 軟件復位 //////////
- VS_Write_Reg(0x00,0x08,0x04); // 軟件復位,向模式寄存器寫入0x0804即可
- /////////// 初始化 //////////
- VS_Write_Reg(0x03,0x98,0x00); // 時鐘設置,3倍頻
- VS_Write_Reg(0x0b,0x00,0x00); // 音量設置,左右聲道均最大音量
-
- VS_XDCS=0; // 打開數據片選,注意此時XCS(片選)為高電平
- SPI_WriteByte(0); // 寫入數據,這里寫入4個字節00或FF,是無關數據,用來啟動數據傳輸
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- VS_XDCS=1; // 關閉數據片選
- if(retry>=200)return 1; // 硬件復位失敗
- else return 0; // 硬件復位成功
- }
- /******************************************************************
- 功能:向VS1003寫入一個字節的音頻數據(即用于播放的數據)
- 參數:dat是要寫入的字節
- ******************************************************************/
- void VS_Send_Dat(unsigned char dat)
- {
- VS_XDCS=0; // 打開數據片選
- VS_DREQ=1;
- while(!VS_DREQ); // VS1003的DREQ為高才能寫入數據
- SPI_WriteByte(dat); // 通過SPI向VS1003寫入一個字節的音頻數據
- VS_XDCS=1; // 關閉數據片選
- }
- /******************************************************************
- 功能:向VS1003寫入2048個0,用于清空VS1003的數據緩沖區,在播放完一個完整的音頻(如MP3)
- 后,調用函數,清空VS1003數據緩沖區,為下面的音頻數據(如下一首MP3)作準備。
- ******************************************************************/
- void VS_Flush_Buffer()
- {
- unsigned int i;
- VS_XDCS=0; // 打開數據片選
- for(i=0;i<2048;i++)
- {
- VS_Send_Dat(0);
- }
- VS_XDCS=1; // 關閉數據片選
- }
- /******************************************************************
- 功能:正弦測試,這是測試VS1003芯片是否正常的有效手段。
- 參數:x決定了正弦測試中產生的正弦波的頻率,直接影響聽到的聲音的頻率
- ******************************************************************/
- void VS_sin_test(unsigned char x)
- {
- VS_Write_Reg(0x00,0x08,0x20); // 啟動正弦測試,
- VS_DREQ=1;
- while(!VS_DREQ); // 等待DREQ變為高電平
- VS_XDCS=0; // 打開數據片選 SDI有效
- SPI_WriteByte(0x53); // 寫入以下8個字節,進入正弦測試
- SPI_WriteByte(0xef); // 正弦測試命令:0x53 0xef 0x6e xx 0x00 0x00 0x00 0x00
- SPI_WriteByte(0x6e);
- SPI_WriteByte(x); // 參數x用來調整正弦測試中正弦波的頻率
- SPI_WriteByte(0); // 比如x=126 (0b 011 11110) FsIdx=011=3 Fs=22050Hz S=11110=30 F=22050Hz X 30 /128 =5168 Hz
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- delay200mS(); // 這里延時一段時間,為了聽到“正弦音”
- SPI_WriteByte(0x45); //寫入以下8個字節,退出正弦測試
- SPI_WriteByte(0x78);
- SPI_WriteByte(0x69);
- SPI_WriteByte(0x74);
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- SPI_WriteByte(0);
- VS_XDCS=1; // 關閉數據片選
- }
- /******************************************************************
- 功能:為VS1003打補丁,獲得實時頻譜,atab與dtab是VS1003頻譜功能補丁碼,在patch.h中
- ******************************************************************/
- void LoadPatch()
- {
- unsigned int i;
- for(i=0;i<943;i++)
- {
- VS_Write_Reg(atab[i],dtab[i]>>8,dtab[i]&0xff);
- }
- }
復制代碼
0.png (26.41 KB, 下載次數: 146)
下載附件
2016-3-29 02:10 上傳
所有完整源碼下載:
第21章 MP3播放器.rar
(9.79 MB, 下載次數: 118)
2016-3-29 02:11 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|