国产免费AV|泡泡玛特欧洲总部将设在伦敦|中文天堂网www新版资源在线|一本久道综合在线中文|国精产品一二三产区的使用方法|香蕉鱼在线观看|www.27eee

 找回密碼
 注冊
搜索

基于STM32+VS1053B的MP3設(shè)計與制作 附源程序

[復(fù)制鏈接]
樓主
STM32_MP3_完整源碼.7z (1.32 MB, 售價: 1 E幣)
一、整體介紹
話不多說,先看看整體原理圖:
基于STM32+VS1053B的MP3設(shè)計與制作 附源程序 210513xlo6pe6se0esq0ll.png

制作出來的實物圖如下:
基于STM32+VS1053B的MP3設(shè)計與制作 附源程序 211030rnl2xdeolexne5u3.jpg


整體上,其實也就四個部分:
(1)    STM32主控部分;
(2)    VS1053B音頻解碼部分;
(3)    按鍵控制部分;
(4)    OLED顯示部分;
上電,通過一系列的測試和檢測后,進(jìn)入音樂播放界面,如圖:
第一排顯示的是我的標(biāo)簽,
第二行,顯示的是當(dāng)前播放歌曲的索引、總歌曲數(shù)目以及當(dāng)前聲音大小,
第三行,顯示的是當(dāng)前歌曲的播放進(jìn)度以及位率,
第四行,顯示的是當(dāng)前歌曲名(因為沒有取字庫,所以我就把他翻譯成了英文,肯定是不準(zhǔn)確的,主要目的只是提示自己)。
此外,通過按鍵,可以對播放歌曲進(jìn)行切換和音量的控制。
下面我們來分別看看這四個部分:
二、模塊介紹
1.     stm32主控
這里我們使用的是stm32F103VET6,內(nèi)部Flash有512K,100pin的外部引腳,屬于大容量芯片,足夠我們diy。對于本設(shè)計,stm32這一塊用到的知識點有:SDIO驅(qū)動SD卡,SPI驅(qū)動VS1053B芯片,IIC驅(qū)動OLED;對于程序,用的是stm32標(biāo)準(zhǔn)庫,小伙伴們可以根據(jù)自己的需要,自行決定是否需要補一下相關(guān)方面的知識。
主控就不再多做介紹了,因為太常見了,這里只是提一下。
2.     VS1053B音頻解碼
這一部分的原理圖如圖:
基于STM32+VS1053B的MP3設(shè)計與制作 附源程序 210552f9jj2d9pxxxn2dnw.png
VS1053B,是一款功能比較強大的音頻解碼芯片,該芯片可以實現(xiàn)對MP3/OGG/WMA/FLAC/WAV/AAC/MIDI等音頻格式的解碼,同時還可以支持ADPCM/OGG等格式的編碼,經(jīng)過我的測試,建議大家用最常用的.MP3 格式的音樂文件;
具體的介紹,請看資料里面的資料手冊,那里說的很清楚,我再多說,顯得就很尷尬了。
3.     按鍵
這個常見到不能再常見了,因為需要按鍵對歌曲進(jìn)行切換和音量大小的控制,所以,這里只是簡單的把他列出來而已。
4.     OLED顯示
OLED只是用來顯示提示的作用,這里我們用的是0.96寸4pin的IIC驅(qū)動的OLED,也是非常常見的玩意兒,不清楚使用的,可以看看相關(guān)的資料。
三、程序代碼:
main.c文件:
  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"                       
  5. #include "oled.h"
  6. #include "bmp.h"
  7. #include "key.h"      
  8. #include "malloc.h"
  9. #include "sdio_sdcard.h"  
  10. #include "vs10xx.h"
  11. #include "mp3player.h"
  12. #include "exfuns.h"
  13. //通過串口打印SD卡相關(guān)信息
  14. void show_sdcard_info(void)
  15. {
  16.          switch(SDCardInfo.CardType)
  17.          {
  18.                   caseSDIO_STD_CAPACITY_SD_CARD_V1_1:printf("Card Type:SDSCV1.1\r\n");break;
  19.                   caseSDIO_STD_CAPACITY_SD_CARD_V2_0:printf("Card Type:SDSCV2.0\r\n");break;
  20.                   caseSDIO_HIGH_CAPACITY_SD_CARD:printf("Card Type:SDHC V2.0\r\n");break;
  21.                   caseSDIO_MULTIMEDIA_CARD:printf("Card Type:MMC Card\r\n");break;
  22.          }      
  23.       printf("Card ManufacturerID:%d\r\n",SDCardInfo.SD_cid.ManufacturerID);    //制造商ID
  24.         printf("CardRCA:%d\r\n",SDCardInfo.RCA);                 //卡相對地址
  25.          printf("CardCapacity:%d MB\r\n",(u32)(SDCardInfo.CardCapacity>>20));        //顯示容量
  26.         printf("CardBlockSize:%d\r\n\r\n",SDCardInfo.CardBlockSize);                          //顯示塊大小
  27. }
  28. intmain(void)
  29. {      
  30.          delay_init();                   //延時函數(shù)初始化         
  31.          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設(shè)置中斷優(yōu)先級分組為組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
  32.          uart_init(115200);          //串口初始化為115200
  33.         LED_Init();                               //初始化與LED連接的硬件接口
  34.          KEY_Init();                                  //初始化按鍵
  35.          VS_Init();                         //初始化VS1053
  36.          delay_ms(1000);   //適當(dāng)延時
  37.          OLED_Init();   //OLED初始化
  38.          OLED_ColorTurn(0);//0正常顯示,1 反色顯示
  39.          OLED_DisplayTurn(0);//0正常顯示 1 屏幕翻轉(zhuǎn)顯示
  40.          OLED_Refresh();  
  41.          delay_ms(1000);   //適當(dāng)延時
  42.          my_mem_init(SRAMIN);                  //初始化內(nèi)部內(nèi)存池
  43.          exfuns_init();                             //為fatfs相關(guān)變量申請內(nèi)存  
  44.         f_mount(fs[0],"0:",1);            //掛載SD卡
  45.         f_mount(fs[1],"1:",1);            //掛載FLASH.
  46.         while(SD_Init())//檢測不到SD卡
  47.          {
  48.                   OLED_ShowString(0,0,"SD_ERROR!!",16);    //錯誤提示信息閃爍
  49.                   delay_ms(200);
  50.                   OLED_ShowString(0,0,"          ",16);
  51.                   delay_ms(200);
  52.                   LED1=!LED1;//DS1閃爍
  53.          }
  54.          show_sdcard_info();       //打印SD卡相關(guān)信息
  55.          //檢測SD卡成功
  56.          OLED_ShowString(0,0,"SD_OK      ",16);         
  57.          delay_ms(1000);
  58.          OLED_ShowString(0,0,"LHSMD- MP3",16);
  59.          while(1)
  60.          {
  61.                   LED1=0;
  62.                   OLED_ShowString(0,16,"storagetest",16);
  63.                   printf("RamTest:0X%04X\r\n",VS_Ram_Test());//打印RAM測試結(jié)果
  64.                   OLED_ShowString(0,16,"sintest    ",16);
  65.                   VS_Sine_Test();   //正弦波測試
  66.                   delay_ms(1000);
  67.                   LED1=1;
  68.                   OLED_Clear();
  69.                   OLED_ShowString(0,0,"  LHSMD - MP3",16);
  70.                   mp3_play();  //放歌操作
  71.          }   
  72. }
復(fù)制代碼
mp3player.c文件:
  1. #include "mp3player.h"
  2. #include "vs10xx.h"         
  3. #include "delay.h"
  4. #include "led.h"
  5. #include "key.h"
  6. //#include "lcd.h"            
  7. #include "malloc.h"
  8. //#include "text.h"
  9. #include "string.h"
  10. #include "exfuns.h"  
  11. #include "ff.h"   
  12. #include "flac.h"     
  13. #include "usart.h"   
  14. #include "oled.h"
  15. //顯示曲目索引
  16. //index:當(dāng)前索引
  17. //total:總文件數(shù)
  18. void mp3_index_show(u16 index,u16 total)
  19. {
  20.          //顯示當(dāng)前曲目的索引,及總曲目數(shù)
  21.          OLED_ShowNum(0,16,index,3,16);
  22.          OLED_ShowString(24,16,"/",16);  
  23.          OLED_ShowNum(32,16,total,3,16);
  24. }
  25. //顯示當(dāng)前音量
  26. void mp3_vol_show(u8 vol)
  27. {                                      
  28.          OLED_ShowString(64,16,"VOL:",16);   
  29.          OLED_ShowNum(105,16,vol,2,16);       //顯示音量
  30. }
  31. u8 time_buf[16];
  32. u16 f_kbps=0;//歌曲文件位率     
  33. //顯示播放時間,比特率 信息
  34. //lenth:歌曲總長度
  35. void mp3_msg_show(u32 lenth)
  36. {      
  37.          staticu16 playtime=0;//播放時間標(biāo)記            
  38.         u16 time=0;// 時間變量
  39.          u16sec=0;// 時間變量
  40.          u16temp=0;   
  41.          if(f_kbps==0xffff)//未更新過
  42.          {
  43.                   playtime=0;
  44.                   f_kbps=VS_Get_HeadInfo();     //獲得比特率
  45.          }               
  46.          time=VS_Get_DecodeTime();//得到解碼時間
  47.          if(playtime==0)playtime=time;
  48.          elseif((time!=playtime)&&(time!=0))//1s時間到,更新顯示數(shù)據(jù)
  49.          {
  50.                   playtime=time;//更新時間                                       
  51.                   temp=VS_Get_HeadInfo();//獲得比特率                                    
  52.                   if(temp!=f_kbps)
  53.                   {
  54.                           f_kbps=temp;//更新KBPS                                          
  55.                   }                          
  56.                   if(f_kbps)sec=(lenth/f_kbps)/125;//得到秒鐘數(shù)(文件長度(字節(jié))/(1000/8)/比特率=持續(xù)秒鐘數(shù)
  57.                   elsesec=0;//非法位率                  
  58.                   //顯示播放時間     
  59.                   sprintf((char*)time_buf,"%02d:%02d/%02d:%02d%003d",time/60,time%60,sec/60,sec%60,f_kbps);
  60.                   OLED_ShowString(0,32,time_buf,16);
  61.                   LED1=!LED1;            //DS0翻轉(zhuǎn)
  62.          }            
  63. }                                         
  64. //得到path路徑下,目標(biāo)文件的總個數(shù)
  65. //path:路徑               
  66. //返回值:總有效文件數(shù)
  67. u16 mp3_get_tnum(u8 *path)
  68. {         
  69.          u8res;
  70.          u16rval=0;
  71.         DIR tdir;                  //臨時目錄
  72.          FILINFOtfileinfo;    //臨時文件信息            
  73.          u8*fn;                                                                          
  74.    res=f_opendir(&tdir,(const TCHAR*)path); //打開目錄
  75.       tfileinfo.lfsize=_MAX_LFN*2+1;                                                //長文件名最大長度
  76.          tfileinfo.lfname=mymalloc(SRAMIN,tfileinfo.lfsize);   //為長文件緩存區(qū)分配內(nèi)存
  77.          if(res==FR_OK&&tfileinfo.lfname!=NULL)
  78.          {
  79.                   while(1)//查詢總的有效文件數(shù)
  80.                   {
  81.                 res=f_readdir(&tdir,&tfileinfo);                       //讀取目錄下的一個文件
  82.                 if(res!=FR_OK||tfileinfo.fname[0]==0)break;      //錯誤了/到末尾了,退出               
  83.                     fn=(u8*)(*tfileinfo.lfname?tfileinfo.lfname:tfileinfo.fname);                       
  84.                           res=f_typetell(fn);  
  85.                           if((res&0XF0)==0X40)//取高四位,看看是不是音樂文件   
  86.                           {
  87.                                    rval++;//有效文件數(shù)增加1
  88.                           }         
  89.                   }  
  90.          }
  91.          myfree(SRAMIN,tfileinfo.lfname);
  92.          returnrval;
  93. }
  94. //播放音樂
  95. void mp3_play(void)
  96. {
  97.          u8res;
  98.         DIR mp3dir;                     //目錄
  99.          FILINFOmp3fileinfo;//文件信息
  100.          u8*fn;                           //長文件名
  101.          u8*pname;                      //帶路徑的文件名
  102.          u16totmp3num;            //音樂文件總數(shù)
  103.          u16curindex;           //圖片當(dāng)前索引
  104.          u8key;                               //鍵值               
  105.         u16 temp;
  106.          u16*mp3indextbl; //音樂索引表
  107.         while(f_opendir(&mp3dir,"0:/music"))//打開圖片文件夾
  108.         {           
  109.                   OLED_ShowString(0,32,"musicfile ERR!",16);            
  110. delay_ms(200);      
  111.                   OLED_ShowString(0,32,"               ",16);
  112.                   delay_ms(200);               
  113.          }                                                                             
  114.          totmp3num=mp3_get_tnum("0:/music");//得到總有效文件數(shù)
  115.       while(totmp3num==NULL)//音樂文件總數(shù)為0         
  116.         {           
  117.                   OLED_ShowString(0,32,"nomusic file  ",16); //沒有音樂文件提示
  118.                   delay_ms(200);                                                            
  119.          }                                                                                         
  120.       mp3fileinfo.lfsize=_MAX_LFN*2+1;                                                  //長文件名最大長度
  121.          mp3fileinfo.lfname=mymalloc(SRAMIN,mp3fileinfo.lfsize);       //為長文件緩存區(qū)分配內(nèi)存
  122.         pname=mymalloc(SRAMIN,mp3fileinfo.lfsize);    //為帶路徑的文件名分配內(nèi)存
  123.         mp3indextbl=mymalloc(SRAMIN,2*totmp3num);        //申請2*totmp3num個字節(jié)的內(nèi)存,用于存放音樂文件索引
  124.         while(mp3fileinfo.lfname==NULL||pname==NULL||mp3indextbl==NULL)//內(nèi)存分配出錯
  125.         {           
  126.                   OLED_ShowString(0,32,"storageERR    ",16);
  127.                   delay_ms(200);                                                   
  128.          }     
  129.          VS_HD_Reset();    //VS1053硬復(fù)位
  130.          VS_Soft_Reset();  //VS1053軟復(fù)位
  131.          vsset.mvol=200;                                                 //默認(rèn)設(shè)置音量為200.
  132.          mp3_vol_show((vsset.mvol-100)/5);    //音量限制在:100~250,顯示的時候,按照公式(vol-100)/5,顯示,也就是0~30   
  133.          //記錄索引
  134.    res=f_opendir(&mp3dir,"0:/music"); //打開目錄
  135.          if(res==FR_OK)
  136.          {
  137.                   curindex=0;//當(dāng)前索引為0
  138.                   while(1)//全部查詢一遍
  139.                   {
  140.                           temp=mp3dir.index;                                                                     //記錄當(dāng)前index
  141.                 res=f_readdir(&mp3dir,&mp3fileinfo);                  //讀取目錄下的一個文件
  142.                 if(res!=FR_OK||mp3fileinfo.fname[0]==0)break;        //錯誤了/到末尾了,退出               
  143.                     fn=(u8*)(*mp3fileinfo.lfname?mp3fileinfo.lfname:mp3fileinfo.fname);                     
  144.                           res=f_typetell(fn);  
  145.                           if((res&0XF0)==0X40)//取高四位,看看是不是音樂文件   
  146.                           {
  147.                                    mp3indextbl[curindex]=temp;//記錄索引
  148.                                    curindex++;
  149.                           }         
  150.                   }
  151.          }   
  152.      curindex=0;                                                                                             //從0開始顯示
  153.      res=f_opendir(&mp3dir,(constTCHAR*)"0:/music");  //打開目錄
  154.          while(res==FR_OK)//打開成功
  155.          {      
  156.                   dir_sdi(&mp3dir,mp3indextbl[curindex]);                       //改變當(dāng)前目錄索引      
  157.        res=f_readdir(&mp3dir,&mp3fileinfo);                  //讀取目錄下的一個文件
  158.        if(res!=FR_OK||mp3fileinfo.fname[0]==0)break;        //錯誤了/到末尾了,退出
  159.            fn=(u8*)(*mp3fileinfo.lfname?mp3fileinfo.lfname:mp3fileinfo.fname);                     
  160.                   strcpy((char*)pname,"0:/music/");                                  //復(fù)制路徑(目錄)
  161.                   strcat((char*)pname,(constchar*)fn);                          //將文件名接在后面
  162.                 OLED_ShowString(0,48,"                ",16);     //清楚之前的顯示
  163.                   OLED_ShowString(0,48,fn,16);                                //顯示歌曲名字
  164.                   mp3_index_show(curindex+1,totmp3num);
  165.                   key=mp3_play_song(pname);                                                //播放這個MP3   
  166.                   if(key==2)                 //上一曲
  167.                   {
  168.                           if(curindex)curindex--;
  169.                           elsecurindex=totmp3num-1;
  170.                 }else if(key<=1)//下一曲
  171.                   {
  172.                           curindex++;                  
  173.                           if(curindex>=totmp3num)curindex=0;//到末尾的時候,自動從頭開始
  174.                 }else break;     //產(chǎn)生了錯誤         
  175.          }                                                                                               
  176.          myfree(SRAMIN,mp3fileinfo.lfname);  //釋放內(nèi)存                          
  177.          myfree(SRAMIN,pname);                                 //釋放內(nèi)存                          
  178.          myfree(SRAMIN,mp3indextbl);                       //釋放內(nèi)存      
  179. }
  180. //播放一曲指定的歌曲                                                                                                                                       
  181. //返回值:0,正常播放完成
  182. //              1,下一曲
  183. //      2,上一曲
  184. //      0XFF,出現(xiàn)錯誤了
  185. u8 mp3_play_song(u8 *pname)
  186. {      
  187.         FIL* fmp3;
  188.    u16 br;
  189.          u8res,rval;        
  190.          u8*databuf;                    
  191.          u16i=0;
  192.          u8key;               
  193.                              
  194.          rval=0;         
  195.          fmp3=(FIL*)mymalloc(SRAMIN,sizeof(FIL));//申請內(nèi)存
  196.          databuf=(u8*)mymalloc(SRAMIN,4096);               //開辟4096字節(jié)的內(nèi)存區(qū)域
  197.          if(databuf==NULL||fmp3==NULL)rval=0XFF;//內(nèi)存申請失敗.
  198.          if(rval==0)
  199.          {         
  200.                VS_Restart_Play();                                           //重啟播放
  201.                   VS_Set_All();                                              //設(shè)置音量等信息                          
  202.                   VS_Reset_DecodeTime();                                          //復(fù)位解碼時間     
  203.                   res=f_typetell(pname);                                   //得到文件后綴                                                                                       
  204.                   if(res==0x4c)//如果是flac,加載patch
  205.                   {      
  206.                           VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN);
  207.                   }                                                                                                                  
  208.                   res=f_open(fmp3,(constTCHAR*)pname,FA_READ);//打開文件        
  209.                 if(res==0)//打開成功.
  210.                   {
  211.                           VS_SPI_SpeedHigh();      //高速                                                   
  212.                           while(rval==0)
  213.                           {
  214.                                    res=f_read(fmp3,databuf,4096,(UINT*)&br);//讀出4096個字節(jié)  
  215.                                    i=0;
  216.                                    do//主播放循環(huán)
  217.                               {     
  218.                                             if(VS_Send_MusicData(databuf+i)==0)//給VS10XX發(fā)送音頻數(shù)據(jù)
  219.                                             {
  220.                                                      i+=32;
  221.                                             }else   
  222.                                             {
  223.                                                      key=KEY_Scan(0);
  224.                                                      switch(key)
  225.                                                      {
  226.                                                              caseKEY1_PRES:
  227.                                                                       rval=1;              //下一曲
  228.                                                                       break;
  229.                                                              caseKEY3_PRES:
  230.                                                                       rval=2;              //上一曲
  231.                                                                       break;
  232.                                                              caseKEY2_PRES:    //音量增加
  233.                                                                       if(vsset.mvol<250)
  234.                                                                       {
  235.                                                                                vsset.mvol+=5;
  236.                                                                               VS_Set_Vol(vsset.mvol);         
  237.                                                                       }elsevsset.mvol=250;
  238.                                                                       mp3_vol_show((vsset.mvol-100)/5);//音量限制在:100~250,顯示的時候,按照公式(vol-100)/5,顯示,也就是0~30   
  239.                                                                       break;
  240.                                                              caseKEY4_PRES:    //音量減
  241.                                                                       if(vsset.mvol>100)
  242.                                                                       {
  243.                                                                                vsset.mvol-=5;
  244.                                                                               VS_Set_Vol(vsset.mvol);         
  245.                                                                        }else vsset.mvol=100;
  246.                                                                       mp3_vol_show((vsset.mvol-100)/5);    //音量限制在:100~250,顯示的時候,按照公式(vol-100)/5,顯示,也就是0~30   
  247.                                                                       break;
  248.                                                      }
  249.                                                      mp3_msg_show(fmp3->fsize);//顯示信息      
  250.                                             }                       
  251.                                    }while(i<4096);//循環(huán)發(fā)送4096個字節(jié)
  252.                                    if(br!=4096||res!=0)
  253.                                    {
  254.                                             rval=0;
  255.                                             break;//讀完了.               
  256.                                    }                                                           
  257.                           }
  258.                           f_close(fmp3);
  259.                   }elserval=0XFF;//出現(xiàn)錯誤         
  260.          }                                                               
  261.          myfree(SRAMIN,databuf);                                    
  262.          myfree(SRAMIN,fmp3);
  263.          returnrval;                                      
  264. }
復(fù)制代碼

沙發(fā)
xingguang 發(fā)表于 2025-3-27 16:42:34 | 只看該作者
看看咋樣
板凳
666、 發(fā)表于 2025-4-14 17:04:21 | 只看該作者
想問一下怎么接線不太會
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則

手機版|小黑屋|ELEOK |網(wǎng)站地圖

GMT+8, 2026-5-26 00:10

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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