Mit dieser Library kann der Audio-DAC (CS43L22) vom Discovery-Board benutzt werden um normale MP3-Files von einem USB-Stick abzuspielen.
(es gibt auch noch eine andere Lib um MP3 aus dem Flash abzuspielen)
Die MP3-Files müssen mit einer Sampling-Frq von 44,1 kHz vorliegen.
Das MP3 kann entweder nur einmal “single” oder endlos “loop” abgespielt werden. Es gibt noch Funktionen für Pause, Resume, Stop und Volume.
Die Funktion “UB_CS43L22_PlayMP3Do” muss ständig zyklisch aufgerufen werden !
Hinweis : Der I2S-Clock und der notwendige PLL muss nicht im “system_stm32f4xx.c-File” eingestellt werden, das wird von der Library erledigt.
MP3-Decoder :
Als MP3-Decoder habe ich Helix-MP3 benutzt (der Link dazu steht im Quellfile)
Um die MP3-Files vom USB-Stick laden zu können, wird die USB-Version der FATFS-Library benötigt und die Library für den USB-MSC im Host-Mode.
Compiler-Settings :
Die “Optimization” muss bei CoIDE auf “-O3″ eingestellt sein, sonst kommt es zu Knackgeräuschen beim abspielen !!
Benutzte Pins :
1 2 3 4 5 6 7 | PB9 = SDA PB6 = SCL PA4 = WS PC7 = MCLK PC10 = SCK PC12 = SD PD4 = Reset |
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : SPI, DMA, MISC Benutzte Librarys : STM32_UB_I2C1, STM32_UB_USB_MSC_HOST |
Enumerationen :
1 2 3 4 5 6 7 8 9 10 11 12 | typedef enum { MP3_OK = 0, // kein Fehler MP3_INIT_ERR, // Fehler beim init MP3_MALLOC_ERR, // nicht genug RAM frei MP3_FILE_ERR, // File Fehler MP3_SYNC_ERR, // kein Sync gefunden MP3_FRQ_ERR, // Fehler bei Samplefrq MP3_FRAME_ERR, // sonstiger Frame fehler MP3_IDATA_ERR, // INDATA_UNDERFLOW MP3_MDATA_ERR, // MAINDATA_UNDERFLOW MP3_DECODE_ERR // sonstige Dekoder fehler }MP3_ERR_t; |
Funktionen :
1 2 3 4 5 6 7 8 9 | ErrorStatus UB_CS43L22_InitMP3(void); // init vom CS43L22 MP3_ERR_t UB_CS43L22_PlayMP3Single(const char* name, uint8_t Volume); // PLAY (einmal) MP3_ERR_t UB_CS43L22_PlayMP3Loop(const char* name, uint8_t Volume); // PLAY (Endlos) CS43L22_STATUS_t UB_CS43L22_PlayMP3Do(void); // muss zyklisch aufgerufen werden void UB_CS43L22_PauseMP3(void); // PAUSE void UB_CS43L22_ResumeMP3(void); // WEITER (nach Pause) void UB_CS43L22_StopMP3(void); // STOP void UB_CS43L22_SetVolumeMP3(uint8_t Volume); // zum einstellen der Lautstärke MP3_ERR_t UB_CS43L22_GetMP3Err(void); // zum auslesen der Fehlernummer |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | //-------------------------------------------------------------- // File : main.c // Datum : 18.08.2013 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.0 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der MP3-Lib (per USB_MSC_Host und FATFS) // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" // // Compiler Optimization auf -O3 einstellen !! //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_usb_msc_host.h" #include "stm32_ub_cs43l22_mp3_fatfs.h" int main(void) { uint8_t play_mode=0; SystemInit(); // Quarz Einstellungen aktivieren // Init vom USB-OTG-Port als MSC-HOST // (zum lesen/schreiben auf einen USB-Stick) UB_USB_MSC_HOST_Init(); // Init vom CS43L22 (im MP3 Mode) if(UB_CS43L22_InitMP3()==SUCCESS) { play_mode=1; // init war ok } while(1) { // pollen vom USB-Status if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) { // wenn USB-Stick erkannt wurde // MP3-Funktion zum abspielen zyklisch aufrufen UB_CS43L22_PlayMP3Do(); if(play_mode==1) { // Media einmal mounten if(UB_Fatfs_Mount(USB_0)==FATFS_OK) { play_mode=2; // abspielen vom MP3-File von USB in einer Endlosloop UB_CS43L22_PlayMP3Loop("skinny.mp3",70); } } } else { // kein USB-Stick vorhanden if(play_mode>1) { play_mode=1; // Media unmounten UB_Fatfs_UnMount(USB_0); } } } } |
Hier die Library zum Download :
ub_stm32f4_cs43l22_usb_mp3_v101
Hier der komplette CooCox-Projektordner zum Download :
Hier das MP3-File zum Download :
Hallo!
Mich würde interessieren, warum man für eine einwandfreie Funktion der Library die Code- Optimierung benötigt. Hat jemand eine Idee dazu?
ich vermute ohne die Optimierung dauert das laden der Daten vom Stick zu lange. So wie ich das noch in Erinnerung habe, läuft die Version wo das MP3-File im Flash liegt auch ohne Optimierung.
Vielen Dank für die Veröffentlichung Deiner Arbeit…
Diese Demo funktioniert ja auch mit nur einer winzigen Parameteranpassung auf dem STM32F401C-Disco, wobei bei der Compilierung von O0-O3 alles ohne Aussetzer funktioniert, soweit ich das hören kann (mp3 mit 320kbit/sec):
in system_stm32f4xx.c(146) die Clocks auf 84Mhz verkleinern und bei der PLL darauf achten, dass USB-clock mit 48 Mhz ganzzahlig “erteilt” werden kann…
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 4 // 8
#define PLL_N 168 // 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 4 // 2
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
Gruss
Danke für den Hinweis.
Ich hätte mal eine frage. Ist in dem Programm schon das auslesen des Namens oder der Aktuellen Position Implementieren? Ich Würde die Daten nämlich gerne auf einem LCD ausgeben. Wie bekomme ich Daten wie Titel und Position und gesamt länge?
MfG
Marcel
das Programm ist ein “minimal” Beispiel. Für Name, Interpret usw müsste man die ID3 Tags auswerten. Im Netz gibts da sicher Beispiele dafür.
Wenn zwischen den einzelnen Liedern die Funktion “UB_USB_MSC_HOST_Do()” aufgerufen wird, kommt es beim Öffnen des nächsten Liedes zu einem Fehler. Die Funktion darf offensichtlich nur zu Anfang aufgerufen werden und nach dem ersten mounten nie mehr wieder, aber dann kann das Programm nicht auf ein Abstecken des USB-Sticks durch den Nutzer reagieren. Die Funktion “UB_USB_MSC_HOST_Do()” muss doch auch später noch immer wieder aufgerufen werden können, ohne dass es danach beim Öffnen einer Datei einen Fehler gibt.
Kennt jemand das Problem / eine Lösung?
hier ist ein player bei dem das funktioniert :
http://mikrocontroller.bplaced.net/wordpress/?page_id=2272
Danke!
Mit dem Beispiel und viel Experimentieren ist mir folgendes klar geworden:
Die Funktion USBH_Process() von STMicroelectronics muss periodisch aufgerufen werden. Aber nicht nach jedem Aufruf dürfen Dateifunktionen wie f_write(), f_open(), … ausgeführt werden. Nur wenn USBH_Process() die callback-Funktion USBH_USR_MSC_Application() aufruft, dürfen danach die Dateifunktionen bis zum nächsten Aufruf von USBH_Process() genutzt werden (oder direkt in der callback-Funktion). Wird das nicht berücksichtigt, kommt es zu Fehlfunktionen, aber nicht unbedingt zu Fehlermeldungen, ganz gefährlich. Also unbedingt in USBH_USR_MSC_Application() irgendein flag setzen…!
Danke für das Projekt!
Ich hätte eine Frage bezüglich der Sampleraten der mp3 Files. Der Dekoder kann ja auch mp3s mit 48kHz Samplerate abspielen. Welche Änderungen wären in den Librarys notwendig um das zu implementieren?
MfG
Felix