找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8817|回復(fù): 8
打印 上一主題 下一主題
收起左側(cè)

第21章 單片機(jī)mp3播放器實(shí)驗(yàn)

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
#
51單片機(jī)輕松入門—基于STC15W4K系列(C語言版)
李友全
編著 詳見:http://www.torrancerestoration.com/bbs/dpj-37954-1.html

21MP3播放器實(shí)驗(yàn)
1 電路圖
2 程序移植

本章實(shí)現(xiàn)的功能是單片機(jī)讀取SD卡中的MP3音樂文件進(jìn)行自動播放。
1 電路圖

1號單片機(jī)與VS1003的接口電路

2 程序移植
程序中比較重要的代碼是VS1003的復(fù)位操作,每首歌曲播放完畢都需執(zhí)行一次復(fù)位操作,否 則后面播放的音樂會出現(xiàn)模糊不清的問題,復(fù)位操作包括硬件復(fù)位與軟件復(fù)位。
void VS_Reset()
{
/////////// 硬件復(fù)位 //////////
unsigned char retry=0;
VS_XDCS=1; // 取消數(shù)據(jù)傳輸 VS_XCS=1; // 取消指令傳輸 VS_XRESET=1;
delay(10);
VS_XRESET=0; // 硬件低電平復(fù)位 delay100mS(); // 延時100ms VS_XRESET=1;
while(VS_DREQ==0&&retry<200) // 等待DREQ為高
{
retry++;
delay50us();
};
delay20ms();
/////////// 軟件復(fù)位 //////////

VS_Write_Reg(0x00,0x08,0x04); // 軟件復(fù)位,向模式寄存器寫入0x0804即可

/////////// 初始化 ////////// VS_Write_Reg(0x03,0x98,0x00); // 時鐘設(shè)置,3倍頻 VS_Write_Reg(0x0b,0x00,0x00); // 音量設(shè)置,左右聲道均最大音量

VS_XDCS=0; // 打開數(shù)據(jù)片選,注意此時XCS(片選)為高電平 SPI_WriteByte(0);

// 寫入數(shù)據(jù),這里寫入4個字節(jié)00或FF,是無關(guān)數(shù)據(jù),用來啟動數(shù)據(jù)傳輸 SPI_WriteByte(0);

SPI_WriteByte(0); SPI_WriteByte(0);

VS_XDCS=1; // 關(guān)閉數(shù)據(jù)片選 if(retry>=200)return 1; // 硬件復(fù)位失敗 else return 0; // 硬件復(fù)位成功

}


部分程序預(yù)覽:
vs1003.c文件:
  1. #include "vs1003.h"
  2. #include "patch.h"
  3. #include "myfun.h"
  4. /****************《51單片機(jī)輕松入門-基于STC15W4K系列》配套例程 *************
  5. ★★★★★★★★★★★★★★★★★★★★★★★★
  6. 《51單片機(jī)輕松入門-基于STC15W4K系列》 一書已經(jīng)由北航出版社正式出版發(fā)行。
  7.   作者親手創(chuàng)作的與教材配套的51雙核實(shí)驗(yàn)板(2個MCU)對程序下載、調(diào)試、仿真方便,不需要外部
  8.   仿真器與編程器,這種設(shè)計方式徹底解決了系統(tǒng)中多個最高優(yōu)先級誰也不能讓誰的中斷競爭問題。
  9.   QQ群:STC51-STM32(3) :515624099 或 STC51-STM32(2):99794374。
  10.         驗(yàn)證信息:STC15單片機(jī)
  11.   郵箱:xgliyouquan@126.com
  12.   ★★★★★★★★★★★★★★★★★★★★★★★★*/
  13. unsigned char bdata dat; //dat是可位尋址的變量

  14. sbit dat7=dat^7;
  15. sbit dat6=dat^6;
  16. sbit dat5=dat^5;
  17. sbit dat4=dat^4;
  18. sbit dat3=dat^3;
  19. sbit dat2=dat^2;
  20. sbit dat1=dat^1;
  21. sbit dat0=dat^0; //取出dat的各個位

  22. /******************************************************************
  23. 功能:IO模擬SPI,發(fā)送一個字節(jié)
  24. ******************************************************************/
  25. void SPI_WriteByte(unsigned char x)
  26. {
  27.         dat=x;              // 將x的值賦給可位尋址的變量dat,以便取出各個位
  28.         
  29.         SPI_SI=dat7;  // 取出第7個位,寫到數(shù)據(jù)線上
  30.         SPI_SCLK=0;
  31.         SPI_SCLK=1;          // 時鐘線產(chǎn)生上升沿,數(shù)據(jù)被寫入
  32.         
  33.         SPI_SI=dat6;
  34.         SPI_SCLK=0;
  35.         SPI_SCLK=1;
  36.         
  37.         SPI_SI=dat5;
  38.         SPI_SCLK=0;
  39.         SPI_SCLK=1;
  40.         
  41.         SPI_SI=dat4;
  42.         SPI_SCLK=0;
  43.         SPI_SCLK=1;
  44.         
  45.         SPI_SI=dat3;
  46.         SPI_SCLK=0;
  47.         SPI_SCLK=1;
  48.         
  49.         SPI_SI=dat2;
  50.         SPI_SCLK=0;
  51.         SPI_SCLK=1;
  52.         
  53.         SPI_SI=dat1;
  54.         SPI_SCLK=0;
  55.         SPI_SCLK=1;
  56.         
  57.         SPI_SI=dat0;
  58.         SPI_SCLK=0;
  59.         SPI_SCLK=1;
  60. }

  61. /******************************************************************
  62. 功能:IO模擬SPI,讀取一個字節(jié)
  63. ******************************************************************/
  64. //unsigned char SPI_ReadByte()
  65. //{  
  66. //        SPI_SO=1;
  67. //        
  68. //        SPI_SCLK=1;
  69. //        delay(1);
  70. //        SPI_SCLK=0;
  71. //        delay(1);
  72. //        dat7=SPI_SO;
  73. //        
  74. //        SPI_SCLK=1;
  75. //        delay(1);
  76. //        SPI_SCLK=0;
  77. //        delay(1);
  78. //        dat6=SPI_SO;
  79. //        
  80. //        SPI_SCLK=1;
  81. //        delay(1);
  82. //        SPI_SCLK=0;
  83. //        delay(1);
  84. //        dat5=SPI_SO;
  85. //        
  86. //        SPI_SCLK=1;
  87. //        delay(1);
  88. //        SPI_SCLK=0;
  89. //        delay(1);
  90. //        dat4=SPI_SO;
  91. //        
  92. //        SPI_SCLK=1;
  93. //        delay(1);
  94. //        SPI_SCLK=0;
  95. //        delay(1);
  96. //        dat3=SPI_SO;
  97. //        
  98. //        SPI_SCLK=1;
  99. //        delay(1);
  100. //        SPI_SCLK=0;
  101. //        delay(1);
  102. //        dat2=SPI_SO;
  103. //        
  104. //        SPI_SCLK=1;
  105. //        delay(1);
  106. //        SPI_SCLK=0;
  107. //        delay(1);
  108. //        dat1=SPI_SO;
  109. //        
  110. //        SPI_SCLK=1;
  111. //        delay(1);
  112. //        SPI_SCLK=0;
  113. //        delay(1);
  114. //        dat0=SPI_SO;
  115. //        
  116. //        return dat;
  117. //}


  118. /******************************************************************
  119. 功能:向VS1003的功能寄存器中寫入數(shù)據(jù)(兩個字節(jié))
  120. 參數(shù):addr是功能寄存器的地址
  121.       hdat是要寫入的高字節(jié)
  122.       ldat是要寫入的低字節(jié)
  123. ******************************************************************/
  124. void VS_Write_Reg(unsigned char addr,unsigned char hdat,unsigned char ldat)
  125. {  
  126.         VS_DREQ=1;            // 51單片機(jī)IO作輸入時先置為1
  127.         while(!VS_DREQ);      // VS1003的DREQ為高電平時才接收數(shù)據(jù)
  128.         VS_XCS=0;             // 打開命令片選,這樣才能對功能寄存器進(jìn)行讀寫
  129.         SPI_WriteByte(0x02);  // 寫入操作碼0x02   00000010 (功能寄存器寫操作)
  130.         SPI_WriteByte(addr);  // 寫入寄存器地址
  131.         SPI_WriteByte(hdat);  // 寫入高字節(jié)
  132.         SPI_WriteByte(ldat);  // 寫入低字節(jié)   
  133.         VS_XCS=1;             // 關(guān)閉命令片選
  134. }

  135. /******************************************************************
  136. 功能:從VS1003的功能寄存器中讀取數(shù)據(jù)(2個字節(jié))
  137. 參數(shù):addr是功能寄存器的地址
  138. 返回:返回從VS1003的功能寄存器中讀到的值
  139. ******************************************************************/
  140. //unsigned int VS_Read_Reg(unsigned char addr)
  141. //{
  142. //        unsigned int temp=0;
  143. //        VS_DREQ=1;            // 51單片機(jī)IO作輸入時先置為1   
  144. //        while(!VS_DREQ);      // VS1003的DREQ為高電平時才接收數(shù)據(jù)
  145. //        VS_XCS=0;                  // 打開命令片選,這樣才能對功能寄存器進(jìn)行讀寫
  146. //        SPI_WriteByte(0x03);  // 讀出操作碼0x03   00000011(功能寄存器讀操作)
  147. //        SPI_WriteByte(addr);  // 寫入寄存器地址
  148. //        temp=SPI_ReadByte();  // 讀高字節(jié)
  149. //        temp<<=8;
  150. //        temp|=SPI_ReadByte(); // 讀取低字節(jié),與高字節(jié)拼成一個整數(shù)
  151. //        
  152. //        VS_XCS=1;                  // 關(guān)閉命令片選
  153. //        return temp;          // 返回讀到的值
  154. //}        

  155. /******************************************************************
  156. 功能:VS1003硬件復(fù)位+軟件復(fù)位+初始化(設(shè)置時鐘頻率及音量)
  157. ******************************************************************/
  158. unsigned char VS_Reset()
  159. {
  160.         ///////////  硬件復(fù)位 //////////
  161.         unsigned char retry=0;
  162.         VS_XDCS=1;             // 取消數(shù)據(jù)傳輸
  163.         VS_XCS=1;             // 取消指令傳輸
  164.         VS_XRESET=1;
  165.         delay(10);                 
  166.         VS_XRESET=0;         // 硬件低電平復(fù)位
  167.         delay100mS();         // 延時100ms
  168.         VS_XRESET=1;  
  169.         while(VS_DREQ==0&&retry<200)   //等待DREQ為高
  170.         {
  171.                 retry++;
  172.                 delay50us();
  173.         };            
  174.         delay20ms();        

  175.         ///////////  軟件復(fù)位 //////////
  176.         VS_Write_Reg(0x00,0x08,0x04); // 軟件復(fù)位,向模式寄存器寫入0x0804即可

  177.         ///////////  初始化 //////////
  178.         VS_Write_Reg(0x03,0x98,0x00); // 時鐘設(shè)置,3倍頻
  179.         VS_Write_Reg(0x0b,0x00,0x00); // 音量設(shè)置,左右聲道均最大音量
  180.         
  181.         VS_XDCS=0;                 // 打開數(shù)據(jù)片選,注意此時XCS(片選)為高電平
  182.         SPI_WriteByte(0);    // 寫入數(shù)據(jù),這里寫入4個字節(jié)00或FF,是無關(guān)數(shù)據(jù),用來啟動數(shù)據(jù)傳輸
  183.         SPI_WriteByte(0);
  184.         SPI_WriteByte(0);
  185.         SPI_WriteByte(0);
  186.         VS_XDCS=1;                 // 關(guān)閉數(shù)據(jù)片選

  187.         if(retry>=200)return 1;          // 硬件復(fù)位失敗
  188.         else return 0;                          // 硬件復(fù)位成功
  189. }

  190. /******************************************************************
  191. 功能:向VS1003寫入一個字節(jié)的音頻數(shù)據(jù)(即用于播放的數(shù)據(jù))
  192. 參數(shù):dat是要寫入的字節(jié)
  193. ******************************************************************/
  194. void VS_Send_Dat(unsigned char dat)
  195. {
  196.         VS_XDCS=0;           // 打開數(shù)據(jù)片選
  197.         VS_DREQ=1;
  198.         while(!VS_DREQ);     // VS1003的DREQ為高才能寫入數(shù)據(jù)
  199.         SPI_WriteByte(dat);  // 通過SPI向VS1003寫入一個字節(jié)的音頻數(shù)據(jù)
  200.         VS_XDCS=1;           // 關(guān)閉數(shù)據(jù)片選
  201. }

  202. /******************************************************************
  203. 功能:向VS1003寫入2048個0,用于清空VS1003的數(shù)據(jù)緩沖區(qū),在播放完一個完整的音頻(如MP3)
  204.       后,調(diào)用函數(shù),清空VS1003數(shù)據(jù)緩沖區(qū),為下面的音頻數(shù)據(jù)(如下一首MP3)作準(zhǔn)備。
  205. ******************************************************************/
  206. void VS_Flush_Buffer()
  207. {
  208.         unsigned int i;
  209.         VS_XDCS=0;                 // 打開數(shù)據(jù)片選
  210.         for(i=0;i<2048;i++)
  211.         {
  212.                 VS_Send_Dat(0);
  213.         }
  214.         VS_XDCS=1;           // 關(guān)閉數(shù)據(jù)片選
  215. }

  216. /******************************************************************
  217. 功能:正弦測試,這是測試VS1003芯片是否正常的有效手段!
  218. 參數(shù):x決定了正弦測試中產(chǎn)生的正弦波的頻率,直接影響聽到的聲音的頻率
  219. ******************************************************************/
  220. void VS_sin_test(unsigned char x)
  221. {
  222.         VS_Write_Reg(0x00,0x08,0x20);  // 啟動正弦測試,
  223.         VS_DREQ=1;
  224.         while(!VS_DREQ);               // 等待DREQ變?yōu)楦唠娖?br />
  225.         VS_XDCS=0;                           // 打開數(shù)據(jù)片選 SDI有效
  226.         SPI_WriteByte(0x53);           // 寫入以下8個字節(jié),進(jìn)入正弦測試
  227.         SPI_WriteByte(0xef);                    // 正弦測試命令:0x53 0xef 0x6e xx 0x00 0x00 0x00 0x00
  228.         SPI_WriteByte(0x6e);
  229.         SPI_WriteByte(x);   // 參數(shù)x用來調(diào)整正弦測試中正弦波的頻率
  230.         SPI_WriteByte(0);   // 比如x=126 (0b 011 11110) FsIdx=011=3   Fs=22050Hz   S=11110=30    F=22050Hz X 30 /128 =5168 Hz
  231.         SPI_WriteByte(0);
  232.         SPI_WriteByte(0);
  233.         SPI_WriteByte(0);

  234.         delay200mS();                  // 這里延時一段時間,為了聽到“正弦音”         

  235.         SPI_WriteByte(0x45);  //寫入以下8個字節(jié),退出正弦測試
  236.         SPI_WriteByte(0x78);
  237.         SPI_WriteByte(0x69);
  238.         SPI_WriteByte(0x74);
  239.         SPI_WriteByte(0);
  240.         SPI_WriteByte(0);
  241.         SPI_WriteByte(0);
  242.         SPI_WriteByte(0);
  243.         VS_XDCS=1;                 // 關(guān)閉數(shù)據(jù)片選  
  244. }

  245. /******************************************************************
  246. 功能:為VS1003打補(bǔ)丁,獲得實(shí)時頻譜,atab與dtab是VS1003頻譜功能補(bǔ)丁碼,在patch.h中
  247. ******************************************************************/
  248. void LoadPatch()
  249. {
  250.         unsigned int i;
  251.         for(i=0;i<943;i++)
  252.         {
  253.                 VS_Write_Reg(atab[i],dtab[i]>>8,dtab[i]&0xff);
  254.         }
  255. }
復(fù)制代碼




所有完整源碼下載: 第21章 MP3播放器.rar (9.79 MB, 下載次數(shù): 118)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂1 踩

相關(guān)帖子

回復(fù)

使用道具 舉報

8#
ID:229361 發(fā)表于 2019-3-17 11:55 | 只看該作者
好東西,感謝樓主分享
回復(fù)

使用道具 舉報

7#
ID:288930 發(fā)表于 2019-1-18 14:01 | 只看該作者
謝謝分享!
回復(fù)

使用道具 舉報

6#
ID:393796 發(fā)表于 2018-10-23 23:45 | 只看該作者
感謝樓主分享
回復(fù)

使用道具 舉報

5#
ID:314710 發(fā)表于 2018-4-24 20:17 | 只看該作者
感謝!
回復(fù)

使用道具 舉報

地板
ID:171696 發(fā)表于 2017-3-19 17:38 | 只看該作者
好東西,正是我到處找的東西
回復(fù)

使用道具 舉報

板凳
ID:142974 發(fā)表于 2016-10-17 17:56 | 只看該作者
有仿真文件嗎 怎么找不到?
回復(fù)

使用道具 舉報

沙發(fā)
ID:140218 發(fā)表于 2016-9-29 23:42 | 只看該作者
好東西,正在研究之中
回復(fù)

使用道具 舉報

樓主
ID:113189 發(fā)表于 2016-8-11 20:25 | 只看該作者
學(xué)習(xí),希望能學(xué)會
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表