logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8][C] Odtwarzacz wav - dziwne dźwięki

lukasz1235 30 Lis 2009 13:50 3969 19
REKLAMA
  • #1 7327255
    lukasz1235
    Poziom 10  
    Witam
    Próbuje zrobić odtwarzać wav na atmega8. Pliki wav mam zapisane na karcie sd. Karta działa prawidłowo, bo bajty wyświetlane na wyświetlaczu są poprawne. Głośnik podpięty bezpośrednio do PB1 i PB2. Kod programu:
    #include <avr/io.h>
    #include <inttypes.h>
    #define F_CPU 8000000
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include "HD44780.c"
    #include "mmc_if.c"
    
    unsigned int i=0;
    unsigned long sector=0;
    char sectorbuffer[512];
    char tekst[10];
    
    int main(void)
    {
    DDRB = 255;
    LCD_Initalize();
    LCD_Clear();
    
    mmc_init();
    mmc_readsector(sector,sectorbuffer);
    
    
    TCCR2 |= (1 << WGM21); // Ustawia timer w tryb CTC
    OCR2 = 15; // Ustawia wartość pożądaną
    TCCR2 |= (1 << CS22); // Ustawia timer z preskalerem Fcpu/64
    TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    sei(); // Zezwolenie globalne na przerwania
    
     TCCR1A=0xA3; 
     TCCR1B=0x09; 
     TCNT1=0x000; 
    
    while(1)
    {
    
    }
    return 0;
    }
    
    ISR(TIMER2_COMP_vect)
    {
    OCR1A = (spi_byte(0xff) << 8 | spi_byte(0xff) )/1000;
    OCR1B = ~OCR1A;
    if (i == 255)
    {
    spi_byte(0xff);					// ignore dummy checksum
    spi_byte(0xff);					// ignore dummy checksum
    mmc_clock_and_release();		// cleanup
    
    i=0;
    sector++;
    mmc_readsector(sector,sectorbuffer);
    }
    else
    {
    i++;
    }
    }

    Mój problem polega na tym, że słychać tylko jakieś dziwne dźwięki, które nie mają nic wspólnego z piosenką zapisaną na karcie. Co robię źle?
  • REKLAMA
  • #2 7327566
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #4 7327817
    lukasz1235
    Poziom 10  
    atom1477 napisał:
    Na moje oko procesor nie wyrabia z odczytem karty SD i tyle.
    W takim razie ten kod powinien działać:
    #define F_CPU 8000000 
    #include <avr/io.h> 
    #include <util/delay.h> 
    #include <avr/interrupt.h>
    #define PWMout OCR1A 
    #define PWMout2 OCR1B
    
    char ton[] = {0x45, 0x04, 0x8D, 0x21, 0xFE, 0x41, 0xB0, 0x57, 0xD1, 0x64, 0x14, 0x65, 0xB0, 0x59, 0xCF, 0x43, 0x9C, 0x25, 0x47, 0x03, 0x54, 0xE0, 0x3E, 0xC1, 0x8D, 0xA9, 0x0D, 0x9C, 0x6C, 0x9A, 0xC0, 0xA4, 0xE9, 0xB9, 0x54, 0xD7, 0x93, 0xF9};
    unsigned int i;
    int main(void) 
    { 
    
    TCCR2 |= (1 << WGM21); // Ustawia timer w tryb CTC
    OCR2 = 15; // Ustawia wartość pożądaną
    TCCR2 |= (1 << CS22); // Ustawia timer z preskalerem Fcpu/64
    TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    sei(); // Zezwolenie globalne na przerwania
    
    
     TCCR1A=0xA3; 
     TCCR1B=0x09; 
     TCNT1=0x000; 
     DDRB = 255;
    
     while(1) 
     { 
    
     } 
    }
    
    ISR(TIMER2_COMP_vect)
    {
    
      PWMout = (ton[i]<<8 | ton[i+1])/1000;
      PWMout2 = ~PWMout;
    if ( i == 37) {i=0;} else {i+=2;}
    }
    A nie działa.
    Ale np. ten kod działa tzn. słychać ton:
    #define F_CPU 8000000 
    #include <avr/io.h> 
    #include <util/delay.h> 
    #include <avr/interrupt.h>
    
    int main(void) 
    { 
    
     TCCR1A=0xA3; 
     TCCR1B=0x09; 
     TCNT1=0x000; 
    DDRB = 255;
    beep(500, 1000);
     while(1) 
     { 
    beep(500, 1000);
     } 
    }
    
    void beep(unsigned int frequency, unsigned int duration)
    {  
      unsigned int i,t,n;  
      t = 125000/frequency*8;  
      n = (250UL*duration)/t;
    
      for(i=0; i < n; i+=2) 
      {
        OCR1A = 100;  
        OCR1B = ~OCR1A;  
        _delay_loop_2(t);
        OCR1A = -100;  
        OCR1B = ~OCR1A; 
    _delay_loop_2(t);
      } 
    }


    avatar napisał:
    a ze tak zapytam jaki to glosnik ?
    Pisze na nim tylko tyle:
    SY
    8ohm
    0.5W
  • REKLAMA
  • #6 7328579
    __Grzegorz__
    Poziom 30  
    Ten plik zawiera dane w postaci danych PCM 8 bit / a może Alaw/uLaw/jakiś ADPCM?

    Otwórz plik w edytorze (np. GoldWave) i sprawdź jego właściwości, ewentualnie zapisz jako PCM 8 bit i sprawdź jeszcze raz...
  • #7 7331566
    lukasz1235
    Poziom 10  
    avatar napisał:
    no to ladnie az 8 ohm i on jest podlaczony bezposrednio do pinow ?
    A jak według ciebie powinno być podłączone?
    __Grzegorz__ napisał:
    Ten plik zawiera dane w postaci danych PCM 8 bit / a może Alaw/uLaw/jakiś ADPCM?
    Zapisuje jako WAV Signed 16bit PCM z tym że przed zapisaniem na kartę usuwam nagłówek
  • #8 7331612
    Freddie Chopin
    Specjalista - Mikrokontrolery
    lukasz1235 napisał:
    avatar napisał:
    no to ladnie az 8 ohm i on jest podlaczony bezposrednio do pinow ?
    A jak według ciebie powinno być podłączone?

    I = U / R = 5V / 8R = 625mA

    Zastanów się teraz jaka jest obciążalność pinu twojego mikrokontrolera.

    4\/3!!
  • #10 7331690
    lukasz1235
    Poziom 10  
    Szanowny przedmówca nie zauważył że do OCR1A/B Przypisuje wartości nie przekraczające 36 czyli 0,2V a to chyba port wytrzyma?
  • #11 7331709
    Konto nie istnieje
    Poziom 1  
  • #12 7331715
    lukasz1235
    Poziom 10  
    To nic nie dało
  • REKLAMA
  • #13 7331844
    Freddie Chopin
    Specjalista - Mikrokontrolery
    O czym ty w ogóle piszesz? To że wpisujesz małe wartości to nie znaczy, że będziesz miał małe napięcie, bo masz tam przebieg prostokątny. I nie jest to kwestia "wytrzymania" pinu (bo nawet jak go przypniesz do masy, to też wytrzyma), tylko tego, że wcale nie masz tam przebiegu którego byś się spodziewał. Pozatym - czy uważasz że głośnik, który zwykle ma kilkanaście - kilkadziesiąt V, działa dobrze na tych ułamkach które mu podajesz? Błagam...

    4\/3!!
  • #14 7331960
    ktrot
    Poziom 20  
    Cytat:
    I = U / R = 5V / 8R = 625mA


    Bez przesady. Pin to nie akumulator z Rw=0,1R.

    I = 5V/(37 + 8 )=111mA (datasheet mega8 complete figure 147)

    Oczywiście za dużo ale nie w tym problem z odtwarzaniem.

    OCR1A = (spi_byte(0xff) << 8 | spi_byte(0xff) )/1000; 
    

    Czy funkcja spi_byte zwraca unsigned int? Jeżeli, tak jak wskazuje nazwa, zwraca bajt to ten zapis niewiele ma wspólnego z tym co chcesz osiągnąć. Ponadto zamiast /1000 uzyj /1024 (czyli >>10).
  • #15 7332188
    m.bartczak
    Poziom 16  
    Jakoś cały czas nie wiem czemu to miałoby działać bez konwersji DA.

    Dla zabawy na początek proponuję zwykła drabinkę rezystorów, taki prymitywny covox (schematy są na sieci dostępne łatwo, ale jakby były trudności: http://www.filety.net/arty/sprzet/samplecovox/covox.png)

    I potem pod wzmacniacz, molestowanie Atmegi głośnikiem podpiętym bezpośrednio to troszkę okrutne.

    *poprawka* prawda, PWM będzie oczywiście działać... ale i tak uważam że drabinka rezystorów jest łatwiejsza do oprogramowania...
  • #16 7332301
    Konto nie istnieje
    Poziom 1  
  • #17 7336212
    lukasz1235
    Poziom 10  
    Na karcie zapisałem plik wav 1kHz unsigned 8bit i dla tego kodu:
    #include <avr/io.h>
    #include <inttypes.h>
    #define F_CPU 8000000
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include "HD44780.c"
    #include "mmc_if.c"
    
    unsigned int i=0;
    unsigned long sector=0;
    
    int main(void)
    {
    DDRB = 255;
    LCD_Initalize();
    LCD_Clear();
    
    mmc_init();
    mmc_readsector(sector,sectorbuffer);
    
    
    TCCR2 |= (1 << WGM21); // Ustawia timer w tryb CTC
    OCR2 = 125; // Ustawia wartość pożądaną na 1khz
    TCCR2 |= (1 << CS22); // Ustawia timer z preskalerem Fcpu/64
    TIMSK |= (1 << OCIE2); // Zezwolenie na przerwania dla CTC
    sei(); // Zezwolenie globalne na przerwania
    
     TCCR1A=0xA3; 
     TCCR1B=0x09; 
     TCNT1=0x000; 
    
    
    while(1)
    {
    
    }
    return 0;
    }
    
    ISR(TIMER2_COMP_vect)
    {
    OCR1A = (spi_byte(0xff)-128);
    OCR1B = ~OCR1A;
    if (i == 511)
    {
    spi_byte(0xff);					// ignore dummy checksum
    spi_byte(0xff);					// ignore dummy checksum
    mmc_clock_and_release();		// cleanup
    
    i=0;
    sector++;
    mmc_readsector(sector,sectorbuffer);
    }
    else
    {
    i++;
    }
    }
    Słychać tylko trzaski.
  • #18 7336242
    piti___
    Poziom 23  
    Może zamiast czytać z karty stwórz sobie dużą tablicę (kilka sekund dźwięku) w pamięci flash i zobacz czy czytając z niej dane będzie dobrze słychać.
  • #19 7336275
    arrevalk
    Poziom 25  
    Oj chyba nie bardzo rozumiesz jak dźwięki są przechowywane w postaci cyfrowej.
    To że do pliku zapisujesz dźwięk o częstotliwości 1kHz nie oznacza że jest on z taką częstotliwością próbkowany. A żeby odtworzyć ten dźwięk musisz znać częstotliwość próbkowania z jaką został nagrany. A te dane znajdują się w nagłówku pliku wav(razem z innymi przydatnymi).
    Czyli jeżeli chcesz odtwarzać plik wav 8bit 44,1kHz (np). To potrzebujesz PWM o takiej właśnie częstotliwości (jak łatwo policzyć potrzebujesz częstotliwości ok 12Mhz).
    A trzaski słyszysz bo odtwarzasz ton 1kHz ok 44 razy wolniej (jeżeli częstotliwość próbkowania wynosiła 44,1kHz)
  • #20 7337506
    lukasz1235
    Poziom 10  
    piti___ napisał:
    Może zamiast czytać z karty stwórz sobie dużą tablicę (kilka sekund dźwięku) w pamięci flash i zobacz czy czytając z niej dane będzie dobrze słychać.
    Słychać tylko pisk:
    const unsigned char xx[] = {0x7D,0x7C,0x7C,0x7B,0x7B,0x7A,0x79,0x78,0x77,0x76,0x76, itd.};
    
    ...
    
    ISR(TIMER2_COMP_vect)
    {
    OCR1A = (xx[i]);
    OCR1B = ~OCR1A;
    i++;
    }

    @arrevalk: Pisząc 1kHz miałem na myśli częstotliwość próbkowania, a nie tonu
REKLAMA