LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

Modułowy odtwarzacz MP3 (2)

Praktyczne testy

Ponieważ napięcia zasilające i interfejs sterujący jest taki sam jak w module YX5300, zastosowałem taki sam układ testowy z modułem Microstick II, wyświetlaczem OLED i enkoderem. Dokładnie w taki sam sposób został skonfigurowany układ UART oraz obsługa wyświetlacza i enkodera.

Odtwarzanie

Funkcje komend zapisują bufor BufCmd kolejnymi bajtami przesyłanymi przez UART do modułu. Na listingu 7 jest pokazana funkcja PlayMp3() wysyłająca komendę PLAY o kodzie 01h.

void PlayMp3(void)
{
    BufCmd[0]=0x7e;	//bajt startu
    BufCmd[1]=0x02;	//bajt liczby danych
    BufCmd[2]=0x01;	//bajt komendy PLAY
    BufCmd[3]=0xef;	//bajt stopu 
    DispTxt(0,0,"PLAY TRACK ", 16,1);  
    RefreshRAM();
    WriteCmdMp3(BufCmd,4);
}

Listing 7. Komenda PLAY

Najpierw do bufora BufCmd[] są zapisywane bajty: startu, ilości danych, kodu komendy i stopu. Potem na ekranie wyświetlacza jest wyświetlana informacja o uruchomieniu odtwarzania „PLAY TRACK” i wywoływana jest funkcja WriteCmdMp3() z argumentami: wskaźnikiem na bufor z bajtami do wysłania i ilością danych do wysłania.

uint8_t WriteCmdMp3(uint8_t *buf,uint8_t len){
    uint8_t i,status;
   uint8_t bufor[10];
    for(i=0;i<len;i++)	//wysłanie zadanej liczby bajtów
    UART1_Write(buf[i]); 
    Delay_ms(50);		//odczekanie na odpowiedź
    
     status=UART1_TransferStatusGet();
          
      if((status&2)==2)	//czy odebrano jakieś znaki 
      {
          UART1_ReadBuffer(bufor,8);//zapisanie bufora odebranymi znakami 
          
          if(bufor[0]=='O'&&bufor[1]=='K')//czy komenda prawidłowa
          {DispTxt(0,20,"ok!", 16,1);
          RefreshRAM();
              return(0);}
          if(bufor[0]=='E')//czy komenda nie rozpoznana
          {  DispTxt(0,20,"err", 16,1);
          RefreshRAM();
              return(1);}
      else
      {  DispTxt(0,20,"NACK", 16,1);//odebrano inne znaki (nie potwierdzenie) 
          RefreshRAM();
              return(2);}

      }
     DispTxt(0,20,"NOE", 16,1);//nie odebrano żadnych znaków
     RefreshRAM();
     return(3);

} 

Listing 8. Funkcja wysłania bajtów komendy

Po wysłaniu bajtów komendy program odczekuje 50 ms na odebranie potwierdzenia. To dużo więcej niż potrzeba. Każdy bajt to 10 bitów przesyłanych z prędkością 9600 bitów na sekundę. Czyli przesłanie jednego bajtu trwa 1/9600*10=1,04 ms . Trzy bajty potwierdzenia to ok 3 ms, 4 bajty odpowiedzi po komendach o status modułu to ok 4ms . Jednak przy obserwowaniu transmisji na oscyloskopie widać było, że moduł nie odsyła odpowiedzi natychmiast.

Program sprawdza czy bajty zostały odebrane testując status transmisji funkcją UART1_TransferStatusGet();. W innych implementacjach użytkownik musi sobie zapewnić możliwość odbierania bajtów i sygnalizację odebrania.

Po odebraniu odpowiedzi następuje analiza odebranych znaków. Wykrycie znaków „OK” oznacza prawidłowo odebrana komendę, wykrycie znaku „E” oznacza niezidentyfikowane polecenie, wykrycie innych znaków jest sygnalizowane brakiem potwierdzenia NACK. Komendy PAUZA i STOP zostały pokazane na listingu 9.

uint8_t PauseMp3(void)
{
    BufCmd[0]=0x7e;
    BufCmd[1]=0x02;
    BufCmd[2]=0x02;
    BufCmd[3]=0xef;
    DispTxt(0,0,"PAUSE     ", 16,1);  
    RefreshRAM();
    return(WriteCmdMp3(BufCmd,4));
}
uint8_t StopMp3(void)
{
    BufCmd[0]=0x7e;
    BufCmd[1]=0x02;
    BufCmd[2]=0x0e;
    BufCmd[3]=0xef;
    return(WriteCmdMp3(BufCmd,4));
}

Listing 9. Komedy PAUZA i STOP

Głośność

Z zestawu komend konfigurujących najczęściej używana będzie komenda ustawiania głośności – listing 10.

uint8_t VolMp3(uint8_t vol){
    BufCmd[0]=0x7e;
    BufCmd[1]=0x03;//liczba bajtów
    BufCmd[2]=0x31;//kod komendy
    BufCmd[3]=vol;  //ustawiana wartość
    BufCmd[4]=0xef;//bajt stopu 
    return(WriteCmdMp3(BufCmd,5));   
}

Listing 10. Ustawianie głośności

W tym przypadku po kodzie komendy jest wysyłany jeden bajt argumentu mogący mieć wartość z zakresu 0…30.

Wybór utworu

Do przedstawionych wyżej komend trzeba dołączyć komendę wyboru pliku na podstawie numeru katalogu i numeru pliku (listing 11) i można zbudować prosty ale funkcjonalny odtwarzacz mp3.

uint8_t PlayTrackMP3(uint8_t fld,uint8_t plk ){
    BufCmd[0]=0x7e;
    BufCmd[1]=0x04;
    BufCmd[2]=0x42;//funkcja wybierz folder i plik 
    BufCmd[3]=fld;//numer folderu
    BufCmd[4]=plk;//numer pliku 
    BufCmd[5]=0xef;//bajt stopu 
    DispTxt(0,0,"Play ", 16,1);  
    DispHex(fld,40,0,16);//wyświetl numer folderu
    DispHex(plk,60,0,16);//wyświetl numer pliku 
    RefreshRAM();
    return(WriteCmdMp3(BufCmd,6));  
}

Listing 11. Funkcja wyboru pliku do odtwarzania

Podsumowanie

Pokazane w artykule moduły odtwarzacz MP3 są głównie przeznaczone do zastosowań przemysłowych. Zbudowanie „konsumenckiego” odtwarzacza plików muzycznych mp3 jest również możliwe, ale kłopotliwe. Przeszkodą mogą być narzucone nazwy plików oraz brak możliwości odczytania rzeczywistej nazwy pliku będącej jednocześnie nazwą utworu. Żeby skutecznie wybierać utwory do odtwarzania trzeba za każdym razem zmieniać ich nazwę, tak by zaczynała się od trzycyfrowej liczby.

Ta niedogodność jest jednocześnie zaletą kiedy chcemy wybierać komunikaty głosowe nie na podstawie dowolnej nazwy składającej się ze znaków ASCII, ale na podstawie wartości cyfrowej. Takie rozwiązanie bardzo ułatwia odtwarzanie komunikatów zależnie od jakiejś wartości, na przykład napięcia, mocy, temperatury, itp.

Podczas testów okazało się, że oba moduły radzą sobie z podanymi częstotliwościami próbkowania, ale gorzej jest z przepływnością. Na początku przez zupełny przypadek umieściłem na nośniku pliki z przepływnością 320kb/s. Moduł YX5300 jakoś sobie poradził. Odtwarzacz MP3 z interfejsem USB odtwarzał materiał dźwiękowy ze sporym poziomem szumów i chwilowymi zniekształceniami. Widać było ,że wbudowany mikrokontroler nie bardzo radził sobie z takim plikiem. Materiał nagrany w 64 kB/s i 128 kb/s był odtwarzany z dobrą jakością. Zważywszy na przeznaczenie modułów, trudno to zakwalifikować jako wadę, gdyż przepływność 128 kb/s daje już bardzo dobrą jakość.

Na pewno ze względu na bardzo korzystny stosunek cena/możliwości warto się zainteresować zastosowaniem tego rozwiązania we własnych konstrukcjach. Trzeba jednak pamiętać, że problemem może być stabilność dostaw.

Tomasz Jabłoński

Absolwent Wydziału Elektroniki Politechniki Wrocławskiej, współpracownik miesięcznika Elektronika Praktyczna, autor książek o mikrokontrolerach Microchip i wyświetlaczach graficznych, wydanych nakładem Wydawnictwa BTC. Zawodowo zajmuje się projektowaniem zaawansowanych systemów mikroprocesorowych.