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

Dźwięk z PCM1808 i PCM5102A na STM32F407 brzmi jak przez filtr dolnoprzepustowy

Maniek275 15 Wrz 2024 19:39 543 4
REKLAMA
  • #1 21227643
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    @ElektrodaBot
    Dzień dobry, zmagam się z nietypowym problemem. Zepsuł mi się ostatnio moduł I2S2 MOD podłączony do stm32f407, który zawierał zarówno ADC jak i DAC działający po I2S. Kupiłem coś tańszego - jako ADC PCM1808, oraz jako DAC PCM5102. Wcześniej działałem na full-duplexie, teraz jestem zmuszony działać na half-duplexie. Napisałem prosty program do bypassu dźwięku i podłączyłem pod wzmacniacz. Dźwięk brzmi jak by zastosowano filtr dolnoprzepustowy - szukam już od kilku dni w DS od ADC, DAC i stm32, nie mogę doszukać się problemu, w internecie też raczej nie widziałem kogoś, kto ma taki sam problem. Czy ktoś spotkał się kiedyś z takim problemem, lub wie gdzie szukać poblemu?

    STM32 - STM32F407VET6
    ADC - PCM1808
    DAC - PCM5102A

    Dostępne narzędzia:
    multimetr, oscyloskop FNIRSI1014d(raczej podchodzący pod zabawkę, aczkolwiek do prostych napraw dobry), analizator logiczny do 48MHz działający na Pulseview

    Poniżej kod, i niektóre ustawienia:
    /* USER CODE BEGIN Header */
    
     * Copyright (c) 2024 STMicroelectronics.
     * All rights reserved.
     *
     * This software is licensed under terms that can be found in the LICENSE file
     * in the root directory of this software component.
     * If no LICENSE file comes with this software, it is provided AS-IS.
     *
     ******************************************************************************
     */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    I2S_HandleTypeDef hi2s2;
    I2S_HandleTypeDef hi2s3;
    DMA_HandleTypeDef hdma_spi2_rx;
    DMA_HandleTypeDef hdma_spi3_tx;
    
    TIM_HandleTypeDef htim2;
    
    /* USER CODE BEGIN PV */
    
    uint16_t tx_buf[8];
    uint16_t rx_buf[8];
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    void PeriphCommonClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_DMA_Init(void);
    static void MX_I2S2_Init(void);
    static void MX_TIM2_Init(void);
    static void MX_I2S3_Init(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    void PCM1808_Init(void) {
       HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);
       HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);
       HAL_GPIO_WritePin(GPIOD, GPIO_PIN_9, GPIO_PIN_RESET);
    }
    /* USER CODE END 0 */
    
    
    int main(void) {
    
       /* USER CODE BEGIN 1 */
    
       /* USER CODE END 1 */
    
       /* MCU Configuration--------------------------------------------------------*/
    
       /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
       HAL_Init();
    
       /* USER CODE BEGIN Init */
    
       /* USER CODE END Init */
    
       /* Configure the system clock */
       SystemClock_Config();
    
       /* Configure the peripherals common clocks */
       PeriphCommonClock_Config();
    
       /* USER CODE BEGIN SysInit */
    
       /* USER CODE END SysInit */
    
       /* Initialize all configured peripherals */
       MX_GPIO_Init();
       MX_DMA_Init();
       MX_I2S2_Init();
       MX_TIM2_Init();
       MX_I2S3_Init();
       /* USER CODE BEGIN 2 */
       PCM1808_Init();
       HAL_TIM_Base_Start_IT(&htim2);
       HAL_I2S_Receive_DMA(&hi2s2, rx_buf, 4);
       HAL_I2S_Transmit_DMA(&hi2s3, tx_buf, 4);
       /* USER CODE END 2 */
    
       /* Infinite loop */
       /* USER CODE BEGIN WHILE */
       while (1) {
          /* USER CODE END WHILE */
    
          /* USER CODE BEGIN 3 */
       }
       /* USER CODE END 3 */
    }
    
    
    void SystemClock_Config(void) {
       RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
       RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
    
       /** Configure the main internal regulator output voltage
        */
       __HAL_RCC_PWR_CLK_ENABLE();
       __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
       /** Initializes the RCC Oscillators according to the specified parameters
        * in the RCC_OscInitTypeDef structure.
        */
       RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
       RCC_OscInitStruct.HSEState = RCC_HSE_ON;
       RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
       RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
       RCC_OscInitStruct.PLL.PLLM = 4;
       RCC_OscInitStruct.PLL.PLLN = 168;
       RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
       RCC_OscInitStruct.PLL.PLLQ = 4;
       if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
          Error_Handler();
       }
    
       /** Initializes the CPU, AHB and APB buses clocks
        */
       RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
             | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
       RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
       RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
       RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
       RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    
       if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
          Error_Handler();
       }
    }
    
    
    void PeriphCommonClock_Config(void) {
       RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
    
       /** Initializes the peripherals clock
        */
       PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
       PeriphClkInitStruct.PLLI2S.PLLI2SN = 123;
       PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
       if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
          Error_Handler();
       }
    }
    
    static void MX_I2S2_Init(void) {
    
       /* USER CODE BEGIN I2S2_Init 0 */
    
       /* USER CODE END I2S2_Init 0 */
    
       /* USER CODE BEGIN I2S2_Init 1 */
    
       /* USER CODE END I2S2_Init 1 */
       hi2s2.Instance = SPI2;
       hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
       hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
       hi2s2.Init.DataFormat = I2S_DATAFORMAT_24B;
       hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
       hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K;
       hi2s2.Init.CPOL = I2S_CPOL_LOW;
       hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
       hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
       if (HAL_I2S_Init(&hi2s2) != HAL_OK) {
          Error_Handler();
       }
       /* USER CODE BEGIN I2S2_Init 2 */
    
       /* USER CODE END I2S2_Init 2 */
    
    }
    
    
    static void MX_I2S3_Init(void) {
    
       /* USER CODE BEGIN I2S3_Init 0 */
    
       /* USER CODE END I2S3_Init 0 */
    
       /* USER CODE BEGIN I2S3_Init 1 */
    
       /* USER CODE END I2S3_Init 1 */
       hi2s3.Instance = SPI3;
       hi2s3.Init.Mode = I2S_MODE_MASTER_TX;
       hi2s3.Init.Standard = I2S_STANDARD_PHILIPS;
       hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B;
       hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
       hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_44K;
       hi2s3.Init.CPOL = I2S_CPOL_LOW;
       hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
       hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
       if (HAL_I2S_Init(&hi2s3) != HAL_OK) {
          Error_Handler();
       }
       /* USER CODE BEGIN I2S3_Init 2 */
    
       /* USER CODE END I2S3_Init 2 */
    
    }
    
    
    static void MX_TIM2_Init(void) {
    
       /* USER CODE BEGIN TIM2_Init 0 */
    
       /* USER CODE END TIM2_Init 0 */
    
       TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
       TIM_MasterConfigTypeDef sMasterConfig = { 0 };
    
       /* USER CODE BEGIN TIM2_Init 1 */
    
       /* USER CODE END TIM2_Init 1 */
       htim2.Instance = TIM2;
       htim2.Init.Prescaler = 0;
       htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
       htim2.Init.Period = 4294967295;
       htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
       htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
       if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
          Error_Handler();
       }
       sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
       if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) {
          Error_Handler();
       }
       sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
       sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
       if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig)
             != HAL_OK) {
          Error_Handler();
       }
       /* USER CODE BEGIN TIM2_Init 2 */
    
       /* USER CODE END TIM2_Init 2 */
    
    }
    
    /**
     * Enable DMA controller clock
     */
    static void MX_DMA_Init(void) {
    
       /* DMA controller clock enable */
       __HAL_RCC_DMA1_CLK_ENABLE();
    
       /* DMA interrupt init */
       /* DMA1_Stream3_IRQn interrupt configuration */
       HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
       HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
       /* DMA1_Stream5_IRQn interrupt configuration */
       HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
       HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
    
    }
    
    
    static void MX_GPIO_Init(void) {
       GPIO_InitTypeDef GPIO_InitStruct = { 0 };
       /* USER CODE BEGIN MX_GPIO_Init_1 */
       /* USER CODE END MX_GPIO_Init_1 */
    
       /* GPIO Ports Clock Enable */
       __HAL_RCC_GPIOC_CLK_ENABLE();
       __HAL_RCC_GPIOH_CLK_ENABLE();
       __HAL_RCC_GPIOA_CLK_ENABLE();
       __HAL_RCC_GPIOB_CLK_ENABLE();
       __HAL_RCC_GPIOD_CLK_ENABLE();
    
       /*Configure GPIO pin Output Level */
       HAL_GPIO_WritePin(FMY_GPIO_Port, FMY_Pin, GPIO_PIN_RESET);
    
       /*Configure GPIO pin Output Level */
       HAL_GPIO_WritePin(GPIOD, MD1_Pin | MD0_Pin, GPIO_PIN_RESET);
    
       /*Configure GPIO pin : FMY_Pin */
       GPIO_InitStruct.Pin = FMY_Pin;
       GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
       GPIO_InitStruct.Pull = GPIO_NOPULL;
       GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
       HAL_GPIO_Init(FMY_GPIO_Port, &GPIO_InitStruct);
    
       /*Configure GPIO pins : MD1_Pin MD0_Pin */
       GPIO_InitStruct.Pin = MD1_Pin | MD0_Pin;
       GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
       GPIO_InitStruct.Pull = GPIO_NOPULL;
       GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
       HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    
       /* USER CODE BEGIN MX_GPIO_Init_2 */
       /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
       /*
        int l_in = (((int) rx_buf[0] << 16) | rx_buf[1]) >> 8;
        int r_in = (((int) rx_buf[2] << 16) | rx_buf[3]) >> 8;
    
        int l_out = l_in;
        int r_out = r_in;
    
        tx_buf[0] = (l_out >> 8) & 0xFFFF;
        tx_buf[1] = l_out & 0xFFFF;
        tx_buf[2] = (r_out >> 8) & 0xFFFF;
        tx_buf[3] = r_out & 0xFFFF;
        */
       for (int i = 0; i < 4; i++) {
          tx_buf[i] = rx_buf[i];
       }
    }
    
    void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
       /*
        int l_in = (((int) rx_buf[4] << 16) | rx_buf[5]) >> 8;
        int r_in = (((int) rx_buf[6] << 16) | rx_buf[7]) >> 8;
    
        int l_out = l_in;
        int r_out = r_in;
    
        tx_buf[4] = (l_out >> 8) & 0xFFFF;
        tx_buf[5] = l_out & 0xFFFF;
        tx_buf[6] = (r_out >> 8) & 0xFFFF;
        tx_buf[7] = r_out & 0xFFFF;
        */
       for (int i = 4; i < 8; i++) {
          tx_buf[i] = rx_buf[i];
       }
    }
    /* USER CODE END 4 */
    
    
    void Error_Handler(void) {
       /* USER CODE BEGIN Error_Handler_Debug */
       /* User can add his own implementation to report the HAL error return state */
       __disable_irq();
       while (1) {
       }
       /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    

    Zrzut ekranu konfiguracji trybu I2S STM32F407.
    Zrzut ekranu ustawień DMA dla STM32F407 z konfiguracją SPI. Schemat blokowy konfiguracji zegara dla mikrokontrolera STM32F407
  • REKLAMA
  • #2 21227790
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8765
    Pomógł: 352
    Ocena: 926
    Maniek275 napisał:
    (...) parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */

    https://obrazki.elektroda.pl/7610684000_1726421856.png
    https://obrazki.elektroda.pl/2590996500_1726421902.png https://obrazki.elektroda.pl/3191504300_1726421928.png
    Dziękuję za szczegółowy opis problemu oraz udostępnienie kodu. Postaram się pomóc w zdiagnozowaniu problemu z dźwiękiem, który brzmi jakby był przepuszczony przez filtr dolnoprzepustowy. Przeanalizujmy kilka potencjalnych przyczyn i możliwych rozwiązań.

    1. Konfiguracja I2S i format danych
    Zauważyłem, że używasz formatu danych 24-bitowego (`I2S_DATAFORMAT_24B`) zarówno dla ADC (PCM1808), jak i DAC (PCM5102A). Upewnij się, że oba układy obsługują ten format. PCM1808 obsługuje 24-bitowe dane, ale PCM5102A może wymagać specyficznej konfiguracji, aby poprawnie odbierać dane w tym formacie.

    Propozycja:
    - Sprawdź, czy PCM5102A jest poprawnie skonfigurowany do odbioru 24-bitowych danych. Jeśli nie, spróbuj zmienić format danych na 16-bitowy (`I2S_DATAFORMAT_16B`) i sprawdź, czy problem nadal występuje.

    2. Częstotliwość próbkowania
    Ustawiłeś częstotliwość próbkowania na 44,1 kHz (`I2S_AUDIOFREQ_44K`). Upewnij się, że zarówno PCM1808, jak i PCM5102A są skonfigurowane do pracy z tą częstotliwością. Jeśli częstotliwość próbkowania nie jest zgodna, może to powodować zniekształcenia dźwięku.

    Propozycja:
    - Użyj oscyloskopu lub analizatora logicznego, aby sprawdzić sygnały zegarowe MCLK, BCLK i LRCLK. Upewnij się, że ich częstotliwości są zgodne z wymaganiami PCM1808 i PCM5102A.

    3. Zegar I2S
    W funkcji `PeriphCommonClock_Config()` ustawiasz wartości PLLI2SN = 123 i PLLI2SR = 2, co generuje zegar dla I2S. Upewnij się, że te wartości są odpowiednie dla częstotliwości próbkowania 44,1 kHz. Jeśli zegar jest nieprawidłowy, może to powodować problemy z jakością dźwięku.

    Propozycja:
    - Sprawdź, czy wartości PLLI2S są poprawnie skonfigurowane. Możesz spróbować zmienić te wartości, aby uzyskać bardziej precyzyjny zegar dla I2S.

    4. Half-duplex a Full-duplex
    Przejście z trybu full-duplex na half-duplex może wprowadzać opóźnienia w przesyłaniu danych, co może wpływać na jakość dźwięku. W half-duplexie dane są przesyłane naprzemiennie, co może powodować problemy z synchronizacją.

    Propozycja:
    - Upewnij się, że dane są przesyłane i odbierane w odpowiednich momentach. Sprawdź, czy nie występują opóźnienia w przesyłaniu danych między ADC a DAC.

    5. Obsługa danych w callbackach
    W funkcjach `HAL_I2S_RxHalfCpltCallback` i `HAL_I2S_RxCpltCallback` po prostu kopiujesz dane z bufora odbiorczego (`rx_buf`) do bufora nadawczego (`tx_buf`). Nie wykonujesz żadnego przetwarzania ani konwersji formatu. Jeśli dane są w formacie 24-bitowym, a PCM5102A oczekuje innego formatu, może to powodować problemy z jakością dźwięku.

    Propozycja:
    - Sprawdź, czy dane są poprawnie przesyłane między ADC a DAC. Możesz spróbować dodać konwersję formatu danych w funkcjach callback, aby upewnić się, że dane są w odpowiednim formacie dla PCM5102A.

    6. Testowanie oddzielnych komponentów
    Spróbuj przetestować PCM1808 i PCM5102A oddzielnie, aby upewnić się, że każdy z układów działa poprawnie. Możesz wygenerować znany sygnał testowy i sprawdzić, czy PCM1808 poprawnie go przetwarza, a następnie sprawdzić, czy PCM5102A poprawnie odtwarza sygnał.

    Propozycja:
    - Użyj oscyloskopu, aby sprawdzić sygnał wyjściowy z PCM5102A przed wzmacniaczem. Sprawdź, czy sygnał jest zgodny z oczekiwaniami.

    7. Zasilanie i połączenia
    Upewnij się, że PCM1808 i PCM5102A są prawidłowo zasilane i że wszystkie połączenia są poprawne. Niewłaściwe zasilanie lub złe połączenia mogą powodować problemy z jakością dźwięku.

    Propozycja:
    - Sprawdź napięcia zasilania obu układów i upewnij się, że są zgodne z dokumentacją. Sprawdź również, czy wszystkie linie I2S są prawidłowo podłączone.

    Podsumowanie:
    1. Sprawdź format danych i częstotliwość próbkowania.
    2. Zweryfikuj konfigurację zegara I2S.
    3. Upewnij się, że dane są poprawnie przesyłane w trybie half-duplex.
    4. Przetestuj oddzielnie PCM1808 i PCM5102A.
    5. Sprawdź zasilanie i połączenia.

    Jeśli problem nadal będzie występował, spróbuj monitorować sygnały za pomocą oscyloskopu i analizatora logicznego, aby zidentyfikować, gdzie dokładnie pojawia się problem.
    Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
  • REKLAMA
  • #3 21228972
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    >>21227790 @ElektrodaBot
    1. Zarówno PCM1808 obsługuje 24-bitowe dane, jak i PCM5102A. Nie mogę zmienić tych wartości, jedyne co to mogę dla PCM1808 ustawić piny MD0 oraz MD1 i FMT, które wpływają na wybór fs w przypadku trybu mastera, i wybór I2S Philips czy Left Justified. Mam wybrany standardowy Philips. W wypadku PCM5102A nie mam nic do wyboru, działa na standard Philips 24-bitowy.

    2. Oba moduły mają autodetekcję częstotliwości, częstotliwości te nie mogą być różne, ponieważ sygnał trafia z PLLI2S, który generuje dokładnie ten sam sygnał dla I2S2 oraz I2S3.

    3. Nie ważne, jaką wartość próbkowania ustawię, czy 44.1, 48 czy 96 kHz, efekt jest ten sam.

    4. Nie powinno być opóźnień dźwięku, czasy wykonywania DMA dla odbierania i wysyłania są takie same, i zastosowane jest podwójne buforowanie, aby zapewnić stały przesył danych.

    5. PCM5102A oczekuje 32-bitowej ramki z 24 bitami danych. Forma wysyłania danych jest poprawnie skonfigurowana, działało tak na PMOD I2S2, tutaj także działa.

    6. Nie mam jak sprawdzić, czy PCM1808 odbiera sygnał, widzę tylko cyfry w debugerze. Z kolei do PCM5102 jeszcze nie pisałem prostego kodu, chociażby sinusoidy, to jest w planach.

    7. Połączenia są poprawne. Zasilanie zgodne z dokumentacjami technicznymi, PCM1808 respektive ma dostarczone zarówno 5 V, jak i 3.3 V, PCM5102A ma dostarczone tylko 3.3 V.
  • REKLAMA
  • #4 21228978
    ElektrodaBot
    AI od OpenAI ChatGPT4
    Posty: 8765
    Pomógł: 352
    Ocena: 926
    Maniek275 napisał:
    (...) gnał, widzę tylko cyfry w debugerze. Z kolei do PCM5102 jeszcze nie pisałem prostego kodu, chociażby sinusoidy, to jest w planach.

    7. Połączenia są poprawne. Zasilanie zgodne z dokumentacjami technicznymi, PCM1808 respektywnie ma dostarczone zarówno 5 V jak i 3.3 V, PCM5102A ma dostarczone tylko 3.3V.
    Dziękuję za dodatkowe informacje i szczegółowy opis problemu. Skoro wykluczyłeś kilka potencjalnych przyczyn, spróbujmy przeanalizować inne możliwe źródła problemu, które mogą powodować efekt przypominający filtr dolnoprzepustowy.

    1. Synchronizacja zegarów I2S
    Chociaż wspomniałeś, że oba układy korzystają z tego samego sygnału zegarowego z PLLI2S, warto dokładnie sprawdzić, czy sygnały zegarowe (MCLK, BCLK, LRCLK) są poprawnie zsynchronizowane między ADC (PCM1808) a DAC (PCM5102A). Nawet niewielkie różnice w synchronizacji mogą powodować zniekształcenia dźwięku.

    Propozycja:
    - Użyj oscyloskopu lub analizatora logicznego, aby sprawdzić, czy sygnały zegarowe są zgodne z oczekiwaniami. Zwróć szczególną uwagę na:
    - MCLK: Powinien być wielokrotnością częstotliwości próbkowania (np. 256 * 44,1 kHz).
    - BCLK: Powinien być zgodny z liczbą bitów na próbkę i częstotliwością próbkowania (np. 2 * 24 * 44,1 kHz).
    - LRCLK: Powinien zmieniać stan co ramkę danych, wskazując lewy lub prawy kanał.

    2. Format danych i ramki I2S
    Zarówno PCM1808, jak i PCM5102A obsługują 24-bitowe dane w formacie I2S Philips, ale PCM5102A oczekuje 32-bitowej ramki z 24-bitowymi danymi. Upewnij się, że dane są poprawnie przesyłane w tym formacie.

    Propozycja:
    - Sprawdź, czy dane są poprawnie wyrównane w 32-bitowej ramce. PCM5102A może wymagać, aby 24-bitowe dane były wyrównane do lewej strony w 32-bitowej ramce. Jeśli dane są źle wyrównane, może to powodować zniekształcenia dźwięku.

    3. Testowanie PCM5102A z sygnałem testowym
    Aby wykluczyć PCM5102A jako źródło problemu, napisz prosty program generujący sygnał testowy (np. sinusoidę) i wyślij go do PCM5102A. Jeśli dźwięk będzie czysty, problem może leżeć po stronie PCM1808 lub w synchronizacji między układami.

    Propozycja:
    - Wygeneruj sygnał sinusoidalny o znanej częstotliwości (np. 1 kHz) i wyślij go do PCM5102A. Sprawdź, czy dźwięk jest odtwarzany poprawnie. Jeśli dźwięk jest zniekształcony, problem może leżeć po stronie PCM5102A lub jego konfiguracji.

    4. Testowanie PCM1808
    Skoro nie masz możliwości bezpośredniego sprawdzenia sygnału z PCM1808, spróbuj podłączyć inne źródło dźwięku do wejścia PCM1808 i sprawdź, czy dane są poprawnie odbierane przez STM32. Możesz również spróbować zapisać dane z PCM1808 do pliku i porównać je z oryginalnym sygnałem.

    Propozycja:
    - Podłącz znane źródło dźwięku (np. generator sygnału lub odtwarzacz MP3) do wejścia PCM1808 i sprawdź, czy dane są poprawnie odbierane przez STM32. Możesz wyświetlić dane w debugerze lub zapisać je do pliku, aby porównać z oryginalnym sygnałem.

    5. Buforowanie danych i DMA
    Zastosowanie podwójnego buforowania DMA to dobry krok, ale warto upewnić się, że dane są poprawnie przesyłane między buforami. Sprawdź, czy nie występują błędy w zarządzaniu buforami, które mogą powodować zniekształcenia dźwięku.

    Propozycja:
    - Dodaj dodatkowe debugowanie w callbackach DMA, aby upewnić się, że dane są poprawnie przesyłane między buforami. Możesz również spróbować zwiększyć rozmiar buforów, aby upewnić się, że nie występują problemy z przepełnieniem bufora.

    6. Zasilanie i połączenia
    Skoro zasilanie jest zgodne z dokumentacją, warto jeszcze raz sprawdzić, czy wszystkie połączenia są poprawne, szczególnie linie I2S. Niewłaściwe połączenia mogą powodować problemy z jakością dźwięku.

    Propozycja:
    - Sprawdź, czy wszystkie linie I2S (MCLK, BCLK, LRCLK, SD) są prawidłowo podłączone i czy nie występują zakłócenia na tych liniach.

    Podsumowanie:
    1. Sprawdź synchronizację zegarów I2S między PCM1808 a PCM5102A.
    2. Upewnij się, że dane są poprawnie wyrównane w 32-bitowej ramce.
    3. Przetestuj PCM5102A z generowanym sygnałem testowym.
    4. Sprawdź, czy PCM1808 poprawnie odbiera dane z zewnętrznego źródła dźwięku.
    5. Zweryfikuj poprawność buforowania danych i DMA.
    6. Sprawdź połączenia i zasilanie.

    Jeśli problem nadal będzie występował, spróbuj monitorować sygnały za pomocą oscyloskopu i analizatora logicznego, aby zidentyfikować, gdzie dokładnie pojawia się problem.
    Możesz mnie wywołać w każdym temacie pisząc @ElektrodaBot. Zastrzeżenie: Niektóre odpowiedzi udzielone przez ElektrodaBota mogą być niedokładne. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi ElektrodaBota powinny być zweryfikowane przez użytkownika. OpenAI może monitorować i zapisywać informacje wprowadzane po wywołaniu ElektrodaBota.
  • #5 21229041
    Maniek275
    Poziom 5  
    Posty: 22
    Ocena: 4
    Przeanalizowałem analizatorem logicznym sygnały - częstotliwości się zgadzają. Odkryłem jednak, że niektóre próbki wchodzące z STM32 na PCM5102 są znacznie zniekształcone w porównaniu do oryginału wychodzącego z PCM1808 do STM32. Sprawdzenie trochę na oko, ale da się zobaczyć, że niekiedy dane są w miarę poprawne, po "ujdzie" aż do kompletnego błędu. Zaczynam pisać program do nadawania tylko przez PCM5102A.
    Zrzut ekranu z analizy sygnałów w programie PulseView, pokazujący sygnały I2S z różnych urządzeń, z notacjami i oznaczeniami charakterystyk sygnałów.
REKLAMA