你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

NUCLEO-H743ZI2上使用SAI PDM采集Infineon-IM69D120失败

[复制链接]
siyou 提问时间:2021-8-15 16:15 / 未解决
第一次用MEMS麦克风,参考Projects\STM32H743I-EVAL\Examples\SAI\SAI_AudioPlayback和<AN5027>把两颗IM69D120连到NUCLEO-H743ZI2的PE2和PE6,得到的PCM数据异常,请帮忙看看是哪里问题?

系统时钟配置如下:

  1. /**
  2.   * @brief  System Clock Configuration
  3.   *         The system Clock is configured as follow :
  4.   *            System Clock source            = PLL (HSE BYPASS)
  5.   *            SYSCLK(Hz)                     = 400000000 (CPU Clock)
  6.   *            HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)
  7.   *            AHB Prescaler                  = 2
  8.   *            D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)
  9.   *            D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)
  10.   *            D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
  11.   *            D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)
  12.   *            HSE Frequency(Hz)              = 8000000
  13.   *            PLL_M                          = 4
  14.   *            PLL_N                          = 400
  15.   *            PLL_P                          = 2
  16.   *            PLL_Q                          = 4
  17.   *            PLL_R                          = 2
  18.   *            VDD(V)                         = 3.3
  19.   *            Flash Latency(WS)              = 4
  20.   * @param  None
  21.   * @retval None
  22.   */
  23. static void SystemClock_Config(void)
  24. {
  25.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  26.   RCC_OscInitTypeDef RCC_OscInitStruct;
  27.   HAL_StatusTypeDef ret = HAL_OK;

  28.   /*!< Supply configuration update enable */
  29.   HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  30.   /* The voltage scaling allows optimizing the power consumption when the device is
  31.      clocked below the maximum system frequency, to update the voltage scaling value
  32.      regarding system frequency refer to product datasheet.  */
  33.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  34.   while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  35.   /* Enable HSE Oscillator and activate PLL with HSE as source */
  36.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  37.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  38.   RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
  39.   RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
  40.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  41.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

  42.   RCC_OscInitStruct.PLL.PLLM = 4;
  43.   RCC_OscInitStruct.PLL.PLLN = 400;
  44.   RCC_OscInitStruct.PLL.PLLFRACN = 0;
  45.   RCC_OscInitStruct.PLL.PLLP = 2;
  46.   RCC_OscInitStruct.PLL.PLLR = 2;
  47.   RCC_OscInitStruct.PLL.PLLQ = 4;

  48.   RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  49.   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
  50.   ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
  51.   if(ret != HAL_OK)
  52.   {
  53.     Error_Handler();
  54.   }

  55. /* Select PLL as system clock source and configure  bus clocks dividers */
  56.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
  57.                                  RCC_CLOCKTYPE_PCLK2  | RCC_CLOCKTYPE_D3PCLK1);

  58.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  59.   RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  60.   RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  61.   RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  62.   RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  63.   RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  64.   RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  65.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
  66.   if(ret != HAL_OK)
  67.   {
  68.     Error_Handler();
  69.   }

  70.   /*activate CSI clock mondatory for I/O Compensation Cell*/
  71.   __HAL_RCC_CSI_ENABLE() ;

  72.   /* Enable SYSCFG clock mondatory for I/O Compensation Cell */
  73.   __HAL_RCC_SYSCFG_CLK_ENABLE() ;

  74.   /* Enables the I/O Compensation Cell */
  75.   HAL_EnableCompensationCell();

  76. }

复制代码



SAI+PDM部分代码如下:
  1. /******************************************************
  2. *                      Macros
  3. ******************************************************/
  4. /* SAI PDM input definitions */
  5. /* SAI input peripheral configuration defines */
  6. #define MIC_IN_SAI_PDMx                           SAI4_Block_A
  7. #define MIC_IN_SAI_PDMx_CLK_ENABLE()              __HAL_RCC_SAI4_CLK_ENABLE()
  8. #define MIC_IN_SAI_PDMx_CLK_DISABLE()             __HAL_RCC_SAI4_CLK_DISABLE()
  9. //#define MIC_IN_SAI_PDMx_FS_SCK_AF                 GPIO_AF8_SAI4
  10. //#define MIC_IN_SAI_PDMx_FS_SCK_ENABLE()           __HAL_RCC_GPIOE_CLK_ENABLE()
  11. //#define MIC_IN_SAI_PDMx_FS_SCK_GPIO_PORT          GPIOE
  12. //#define MIC_IN_SAI_PDMx_FS_PIN                    GPIO_PIN_4
  13. //#define MIC_IN_SAI_PDMx_SCK_PIN                   GPIO_PIN_5

  14. #define MIC_IN_SAI_PDMx_CLK_IN_ENABLE()           __HAL_RCC_GPIOE_CLK_ENABLE()
  15. #define MIC_IN_SAI_PDMx_CLK_IN_PIN                GPIO_PIN_2
  16. #define MIC_IN_SAI_PDMx_CLK_IN_PORT               GPIOE
  17. #define MIC_IN_SAI_PDMx_CLK_AF                    GPIO_AF10_SAI4
  18. #define MIC_IN_SAI_PDMx_DATA_IN_ENABLE()          __HAL_RCC_GPIOE_CLK_ENABLE()
  19. #define MIC_IN_SAI_PDMx_DATA_IN_PIN               GPIO_PIN_6
  20. #define MIC_IN_SAI_PDMx_DATA_IN_PORT              GPIOE
  21. #define MIC_IN_SAI_PDMx_DATA_AF                   GPIO_AF9_SAI4
  22. #define MIC_IN_SAI_PDMx_IRQHandler                SAI4_IRQHandler
  23. #define MIC_IN_SAI_PDMx_IRQ                       SAI4_IRQn
  24. #define MIC_IN_SAI_IRQ_PREPRIO                    ((uint32_t)0x0E)

  25. /* SAI PDM DMA Stream definitions */
  26. #define MIC_IN_SAI_PDMx_DMAx_CLK_ENABLE()         __HAL_RCC_BDMA_CLK_ENABLE()
  27. #define MIC_IN_SAI_PDMx_DMAx_STREAM               BDMA_Channel1
  28. #define MIC_IN_SAI_PDMx_DMAx_REQUEST              BDMA_REQUEST_SAI4_A
  29. #define MIC_IN_SAI_PDMx_DMAx_IRQ                  BDMA_Channel1_IRQn
  30. #define MIC_IN_SAI_PDMx_DMAx_PERIPH_DATA_SIZE     DMA_PDATAALIGN_HALFWORD
  31. #define MIC_IN_SAI_PDMx_DMAx_MEM_DATA_SIZE        DMA_MDATAALIGN_HALFWORD

  32. /* Private define ------------------------------------------------------------*/
  33. #define AUDIO_FREQUENCY       SAI_AUDIO_FREQUENCY_16K
  34. #define AUDIO_CHANNEL_NUMBER  2U
  35. #define AUDIO_BUFFER_SIZE     256U//128U//256U
  36. #define AUDIO_PCM_CHUNK_SIZE  32U

  37. /* Private macro -------------------------------------------------------------*/
  38. /* Audio PDM FS frequency = 128KHz = 8 * 16KHz = 8 * FS_Freq */
  39. #define AUDIO_PDM_GET_FS_FREQUENCY(FS)  (FS * 8)

  40. /* Private typedef -----------------------------------------------------------*/
  41. typedef enum {
  42.   BUFFER_OFFSET_NONE = 0,
  43.   BUFFER_OFFSET_HALF,
  44.   BUFFER_OFFSET_FULL,
  45.   BUFFER_OFFSET_ERROR,
  46. } BUFFER_StateTypeDef;

  47. /* SAI input Handle */
  48. SAI_HandleTypeDef         hSaiMic;
  49. DMA_HandleTypeDef         hSaiMicDma;

  50. /* Buffer containing the PDM samples */
  51. #if defined ( __CC_ARM )  /* !< ARM Compiler */
  52.   /* Buffer location should aligned to cache line size (32 bytes) */
  53.   ALIGN_32BYTES (uint16_t audioPdmBuf[AUDIO_BUFFER_SIZE]) __attribute__((section(".RAM_D3")));
  54. #elif defined ( __ICCARM__ )  /* !< ICCARM Compiler */
  55.   #pragma location=0x38000000
  56.   /* Buffer location should aligned to cache line size (32 bytes) */
  57.   ALIGN_32BYTES (uint16_t audioPdmBuf[AUDIO_BUFFER_SIZE]);
  58. #elif defined ( __GNUC__ )  /* !< GNU Compiler */
  59.   /* Buffer location should aligned to cache line size (32 bytes) */
  60.   ALIGN_32BYTES (uint16_t audioPdmBuf[AUDIO_BUFFER_SIZE]) __attribute__((section(".RAM_D3")));
  61. #endif

  62. /* Buffer containing the PCM samples
  63.    Buffer location should aligned to cache line size (32 bytes) */
  64. ALIGN_32BYTES (uint16_t audioPcmBuf[AUDIO_BUFFER_SIZE]);
  65. //ALIGN_32BYTES (uint16_t pcmChBuf[2][AUDIO_BUFFER_SIZE]);

  66. /* PDM Filters params */
  67. PDM_Filter_Handler_t  PDM_FilterHandler[2];
  68. PDM_Filter_Config_t   PDM_FilterConfig[2];

  69. /* Pointer to PCM data */
  70. __IO uint32_t pcmPtr;//, pcmChPtr;
  71. /* Buffer status variable */
  72. __IO BUFFER_StateTypeDef bufferStatus = BUFFER_OFFSET_NONE;

  73. /**
  74. * @brief  Init PDM Filters.
  75. * @param  AudioFreq: Audio sampling frequency
  76. * @param  ChannelNumber: Number of audio channels in the PDM buffer.
  77. * @retval None
  78. */
  79. static void AUDIO_IN_PDMToPCM_Init(uint32_t AudioFreq, uint32_t ChannelNumber)
  80. {
  81.   uint32_t index = 0;

  82.   /* Enable CRC peripheral to unlock the PDM library */
  83.   __HAL_RCC_CRC_CLK_ENABLE();

  84.   for(index = 0; index < ChannelNumber; index++)
  85.   {
  86.     /* Init PDM filters */
  87.     PDM_FilterHandler[index].bit_order  = PDM_FILTER_BIT_ORDER_LSB;//PDM_FILTER_BIT_ORDER_MSB;
  88.     PDM_FilterHandler[index].endianness = PDM_FILTER_ENDIANNESS_LE;
  89.     PDM_FilterHandler[index].high_pass_tap = 2122358088;
  90.     PDM_FilterHandler[index].out_ptr_channels = ChannelNumber;
  91.     PDM_FilterHandler[index].in_ptr_channels  = ChannelNumber;
  92.     PDM_Filter_Init((PDM_Filter_Handler_t *)(&PDM_FilterHandler[index]));

  93.     /* Configure PDM filters */
  94.     PDM_FilterConfig[index].output_samples_number = AudioFreq/1000;
  95.     PDM_FilterConfig[index].mic_gain = 24;
  96.     PDM_FilterConfig[index].decimation_factor = PDM_FILTER_DEC_FACTOR_64;
  97.     PDM_Filter_setConfig((PDM_Filter_Handler_t *)&PDM_FilterHandler[index], &PDM_FilterConfig[index]);
  98.   }
  99. }

  100. /**
  101.   * @brief  Convert audio format from PDM to PCM.
  102.   * @param  PDMBuf: Pointer to PDM buffer data
  103.   * @param  PCMBuf: Pointer to PCM buffer data
  104.   * @param  ChannelNumber: PDM Channels number.
  105.   * @retval None
  106. */
  107. static void AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf, uint32_t ChannelNumber)
  108. {
  109.   uint32_t index = 0;

  110.   /* Invalidate Data Cache to get the updated content of the SRAM*/
  111.   SCB_InvalidateDCache_by_Addr((uint32_t *)PDMBuf, AUDIO_BUFFER_SIZE);

  112.   for(index = 0; index < ChannelNumber; index++)
  113.   {
  114.     PDM_Filter(&((uint8_t*)(PDMBuf))[index], (uint16_t*)&(PCMBuf[index]), &PDM_FilterHandler[index]);
  115.   }

  116.   /* Clean Data Cache to update the content of the SRAM */
  117.   SCB_CleanDCache_by_Addr((uint32_t*)PCMBuf, AUDIO_PCM_CHUNK_SIZE*2);
  118. }

  119. /**
  120.   * @brief  Microphone SAI interface initialization
  121.   * @param  None
  122.   * @retval None
  123.   */
  124. void MIC_SAI_Init(void)
  125. {
  126.   GPIO_InitTypeDef  GPIO_Init;

  127.   RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;

  128.   /* Configure PLLSAI4A prescalers */
  129.   /* SAI4A: PLL2P = 8MHz/4*128/125 = 2.048MHz */
  130.   RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
  131.   RCC_PeriphCLKInitStruct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
  132.   RCC_PeriphCLKInitStruct.PLL2.PLL2P = 125; // 107--2.4MHz, 125--2.048MHz
  133.   RCC_PeriphCLKInitStruct.PLL2.PLL2Q = 2;
  134.   RCC_PeriphCLKInitStruct.PLL2.PLL2R = 2;
  135.   RCC_PeriphCLKInitStruct.PLL2.PLL2N = 128;
  136.   RCC_PeriphCLKInitStruct.PLL2.PLL2FRACN = 6144.0;
  137.   RCC_PeriphCLKInitStruct.PLL2.PLL2M = 4;
  138.   RCC_PeriphCLKInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;
  139.   RCC_PeriphCLKInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;

  140.   if(HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK)
  141.   {
  142.     Error_Handler();
  143.   }

  144.   //---------------------------------------------------------------------------
  145.   /* SAI MSP Init */
  146.   //---------------------------------------------------------------------------
  147.   /* Enable SAI clock */
  148.   MIC_IN_SAI_PDMx_CLK_ENABLE();

  149.   MIC_IN_SAI_PDMx_CLK_IN_ENABLE();
  150.   MIC_IN_SAI_PDMx_DATA_IN_ENABLE();

  151.   GPIO_Init.Pin = MIC_IN_SAI_PDMx_CLK_IN_PIN;
  152.   GPIO_Init.Mode = GPIO_MODE_AF_PP;
  153.   GPIO_Init.Pull = GPIO_NOPULL;
  154.   GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
  155.   GPIO_Init.Alternate = MIC_IN_SAI_PDMx_CLK_AF;
  156.   HAL_GPIO_Init(MIC_IN_SAI_PDMx_CLK_IN_PORT, &GPIO_Init);

  157.   GPIO_Init.Pull = GPIO_PULLUP;
  158.   GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;
  159.   GPIO_Init.Pin = MIC_IN_SAI_PDMx_DATA_IN_PIN;
  160.   GPIO_Init.Alternate = MIC_IN_SAI_PDMx_DATA_AF;
  161.   HAL_GPIO_Init(MIC_IN_SAI_PDMx_DATA_IN_PORT, &GPIO_Init);

  162.   //MIC_IN_SAI_PDMx_FS_SCK_ENABLE();

  163.   /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins
  164.   GPIO_Init.Pin = MIC_IN_SAI_PDMx_FS_PIN | MIC_IN_SAI_PDMx_SCK_PIN;
  165.   GPIO_Init.Mode = GPIO_MODE_AF_PP;
  166.   GPIO_Init.Pull = GPIO_NOPULL;
  167.   GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
  168.   GPIO_Init.Alternate = MIC_IN_SAI_PDMx_FS_SCK_AF;
  169.   HAL_GPIO_Init(MIC_IN_SAI_PDMx_FS_SCK_GPIO_PORT, &GPIO_Init); */

  170.   /* Enable the DMA clock */
  171.   MIC_IN_SAI_PDMx_DMAx_CLK_ENABLE();

  172.   /* Configure the hdma_sai_rx handle parameters */
  173.   hSaiMicDma.Init.Request             = MIC_IN_SAI_PDMx_DMAx_REQUEST;
  174.   hSaiMicDma.Init.Direction           = DMA_PERIPH_TO_MEMORY;
  175.   hSaiMicDma.Init.PeriphInc           = DMA_PINC_DISABLE;
  176.   hSaiMicDma.Init.MemInc              = DMA_MINC_ENABLE;
  177.   hSaiMicDma.Init.PeriphDataAlignment = MIC_IN_SAI_PDMx_DMAx_PERIPH_DATA_SIZE;
  178.   hSaiMicDma.Init.MemDataAlignment    = MIC_IN_SAI_PDMx_DMAx_MEM_DATA_SIZE;
  179.   hSaiMicDma.Init.Mode                = DMA_CIRCULAR;
  180.   hSaiMicDma.Init.Priority            = DMA_PRIORITY_HIGH;
  181.   hSaiMicDma.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
  182.   hSaiMicDma.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
  183.   hSaiMicDma.Init.MemBurst            = DMA_MBURST_SINGLE;
  184.   hSaiMicDma.Init.PeriphBurst         = DMA_MBURST_SINGLE;

  185.   hSaiMicDma.Instance = MIC_IN_SAI_PDMx_DMAx_STREAM;

  186.   /* Associate the DMA handle */
  187.   __HAL_LINKDMA(&hSaiMic, hdmarx, hSaiMicDma);

  188.   /* Deinitialize the Stream for new transfer */
  189.   HAL_DMA_DeInit(&hSaiMicDma);

  190.   /* Configure the DMA Stream */
  191.   HAL_DMA_Init(&hSaiMicDma);

  192.   /* SAI DMA IRQ Channel configuration */
  193.   HAL_NVIC_SetPriority(MIC_IN_SAI_PDMx_DMAx_IRQ, MIC_IN_SAI_IRQ_PREPRIO, 0);
  194.   HAL_NVIC_EnableIRQ(MIC_IN_SAI_PDMx_DMAx_IRQ);
  195.   //---------------------------------------------------------------------------

  196.   /* SAI PDM Input init */
  197.   __HAL_SAI_RESET_HANDLE_STATE(&hSaiMic);

  198.   hSaiMic.Instance                 = MIC_IN_SAI_PDMx;
  199.   hSaiMic.Init.AudioMode           = SAI_MODEMASTER_RX;
  200.   hSaiMic.Init.Synchro             = SAI_ASYNCHRONOUS;
  201.   hSaiMic.Init.SynchroExt          = SAI_SYNCEXT_DISABLE;
  202.   hSaiMic.Init.OutputDrive         = SAI_OUTPUTDRIVE_DISABLE;
  203.   hSaiMic.Init.NoDivider           = SAI_MASTERDIVIDER_DISABLE;
  204.   hSaiMic.Init.FIFOThreshold       = SAI_FIFOTHRESHOLD_HF;//SAI_FIFOTHRESHOLD_EMPTY;//SAI_FIFOTHRESHOLD_HF;
  205.   hSaiMic.Init.AudioFrequency      = AUDIO_PDM_GET_FS_FREQUENCY(AUDIO_FREQUENCY);//AUDIO_FREQUENCY;//AUDIO_PDM_GET_FS_FREQUENCY(AUDIO_FREQUENCY);
  206.   hSaiMic.Init.Mckdiv              = 0;
  207.   hSaiMic.Init.MckOverSampling     = SAI_MCK_OVERSAMPLING_DISABLE;
  208.   hSaiMic.Init.MonoStereoMode      = SAI_STEREOMODE;//SAI_MONOMODE;//SAI_STEREOMODE;
  209.   hSaiMic.Init.CompandingMode      = SAI_NOCOMPANDING;
  210.   hSaiMic.Init.TriState            = SAI_OUTPUT_NOTRELEASED;
  211.   hSaiMic.Init.PdmInit.Activation  = ENABLE;
  212.   hSaiMic.Init.PdmInit.MicPairsNbr = 1;
  213.   hSaiMic.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
  214.   hSaiMic.Init.Protocol            = SAI_FREE_PROTOCOL;
  215.   hSaiMic.Init.DataSize            = SAI_DATASIZE_16;
  216.   hSaiMic.Init.FirstBit            = SAI_FIRSTBIT_LSB;//SAI_FIRSTBIT_MSB;//SAI_FIRSTBIT_LSB;
  217.   hSaiMic.Init.ClockStrobing       = SAI_CLOCKSTROBING_FALLINGEDGE;//SAI_CLOCKSTROBING_RISINGEDGE;

  218.   hSaiMic.FrameInit.FrameLength       = 16;
  219.   hSaiMic.FrameInit.ActiveFrameLength = 1;
  220.   hSaiMic.FrameInit.FSDefinition      = SAI_FS_STARTFRAME;
  221.   hSaiMic.FrameInit.FSPolarity        = SAI_FS_ACTIVE_HIGH;
  222.   hSaiMic.FrameInit.FSOffset          = SAI_FS_FIRSTBIT;

  223.   hSaiMic.SlotInit.FirstBitOffset = 0;
  224.   hSaiMic.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
  225.   hSaiMic.SlotInit.SlotNumber     = 1;
  226.   hSaiMic.SlotInit.SlotActive     = 0x0000FFFF;//SAI_SLOTACTIVE_0;

  227.   /* DeInit SAI PDM input */
  228.   HAL_SAI_DeInit(&hSaiMic);

  229.   /* Init SAI PDM input */
  230.   if(HAL_OK != HAL_SAI_Init(&hSaiMic))
  231.   {
  232.     Error_Handler();
  233.   }

  234.   /* Enable SAI to generate clock used by audio driver */
  235.   __HAL_SAI_ENABLE(&hSaiMic);

  236.   /* Init PDM Filters */
  237.   AUDIO_IN_PDMToPCM_Init(AUDIO_FREQUENCY, AUDIO_CHANNEL_NUMBER);

  238.   /* Initialize Rx buffer status */
  239.   bufferStatus = BUFFER_OFFSET_NONE;
  240. }

  241. void MIC_Receive_Start(void)
  242. {
  243.   /* Start the PDM data reception process */
  244.   if(HAL_OK != HAL_SAI_Receive_DMA(&hSaiMic, (uint8_t*)audioPdmBuf, AUDIO_BUFFER_SIZE))
  245.   {
  246.     Error_Handler();
  247.   }
  248. }

  249. void MIC_Data_Process(void)
  250. {
  251.   uint16_t i;

  252.   /* Wait Rx half transfer event */
  253.   if (bufferStatus == BUFFER_OFFSET_HALF) {

  254.     /* Convert the first half of PDM data to PCM */
  255.     AUDIO_IN_PDMToPCM((uint16_t*)&audioPdmBuf[0], &audioPcmBuf[pcmPtr], AUDIO_CHANNEL_NUMBER);
  256. /*
  257.     for (i =0; i<AUDIO_PCM_CHUNK_SIZE/2; i++)
  258.     {
  259.       pcmChBuf[0][pcmChPtr+i] = audioPcmBuf[pcmPtr+2*i];
  260.       pcmChBuf[1][pcmChPtr+i] = audioPcmBuf[pcmPtr+2*i+1];
  261.     }
  262. */
  263.     /* Update pcmPtr */
  264.     pcmPtr += AUDIO_PCM_CHUNK_SIZE;
  265.     //pcmChPtr += AUDIO_PCM_CHUNK_SIZE/2;
  266.     //qst_util_printf("h:%d\r\n", pcmPtr);

  267.     /* Initialize Rx buffer status */
  268.     bufferStatus &= BUFFER_OFFSET_NONE;
  269.   } else if (bufferStatus == BUFFER_OFFSET_FULL) {
  270.     /* Wait Rx transfer complete event */
  271.     //while(bufferStatus != BUFFER_OFFSET_FULL);

  272.     /* Convert the second half of PDM data to PCM */
  273.     AUDIO_IN_PDMToPCM((uint16_t*)&audioPdmBuf[AUDIO_BUFFER_SIZE/2], &audioPcmBuf[pcmPtr], AUDIO_CHANNEL_NUMBER);
  274. /*
  275.     for (i =0; i<AUDIO_PCM_CHUNK_SIZE/2; i++)
  276.     {
  277.       pcmChBuf[0][pcmChPtr+i] = audioPcmBuf[pcmPtr+2*i];
  278.       pcmChBuf[1][pcmChPtr+i] = audioPcmBuf[pcmPtr+2*i+1];
  279.     }
  280. */
  281.     /* Update pcmPtr */
  282.     pcmPtr += AUDIO_PCM_CHUNK_SIZE;
  283.     //pcmChPtr += AUDIO_PCM_CHUNK_SIZE/2;
  284.     //qst_util_printf("f:%d\r\n", pcmPtr);

  285.     /* Initialize Rx buffer status */
  286.     bufferStatus &= BUFFER_OFFSET_NONE;

  287.     if(pcmPtr >= AUDIO_BUFFER_SIZE)
  288.     {
  289.       //qst_util_printf("P:%d\r\n", pcmPtr);
  290.       pcmPtr = 0;
  291.       //pcmChPtr = 0;
  292.       qst_util_serial_send((uint8_t *)audioPcmBuf, 2*AUDIO_BUFFER_SIZE);
  293.       //qst_util_serial_send((uint8_t *)pcmChBuf[0], AUDIO_BUFFER_SIZE);
  294.     }

  295.     /* Toggle LED1 */
  296.     BSP_LED_Toggle(LED1);
  297.   } else if (bufferStatus == BUFFER_OFFSET_ERROR) {
  298.     qst_util_printf("SAI Error: %d\r\n", HAL_SAI_GetError(&hSaiMic));

  299.     /* Initialize Rx buffer status */
  300.     bufferStatus &= BUFFER_OFFSET_NONE;
  301.   }

  302. }

  303. /**
  304.   * @brief  Rx Transfer completed callbacks.
  305.   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains
  306.   *                the configuration information for SAI module.
  307.   * @retval None
  308.   */
  309. void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
  310. {

  311.   bufferStatus = BUFFER_OFFSET_FULL;
  312. }

  313. /**
  314.   * @brief  Rx Transfer Half completed callbacks
  315.   * @param  hsai : pointer to a SAI_HandleTypeDef structure that contains
  316.   *                the configuration information for SAI module.
  317.   * @retval None
  318.   */
  319. void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
  320. {

  321.   bufferStatus = BUFFER_OFFSET_HALF;
  322. }


  323. /**
  324.   * @brief SAI error callback.
  325.   * @param  hsai pointer to a SAI_HandleTypeDef structure that contains
  326.   *              the configuration information for SAI module.
  327.   * @retval None
  328.   */
  329. void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
  330. {
  331.   /* Prevent unused argument(s) compilation warning */
  332.   UNUSED(hsai);

  333.   bufferStatus = BUFFER_OFFSET_ERROR;
  334. }

复制代码
Main函数处理代码如下:
  1.   MIC_SAI_Init();

  2.   MIC_Receive_Start();

  3.   /* Infinite loop */
  4.   while (1)
  5.   {
  6.     MIC_Data_Process();

  7.     if(ButtonState != 0)
  8.     {
  9.      /* Toggle LED1 */
  10.       BSP_LED_Toggle(LED1);
  11.       ButtonState = 0;
  12.       HAL_Delay(5); /* to avoid bounce when button pressed */
  13.     }
  14.   }
复制代码


收藏 评论2 发布时间:2021-8-15 16:15

举报

2个回答
siyou 回答时间:2021-8-15 16:23:27
输出的PCM数据为: audioPcmBuf.zip (28.39 KB, 下载次数: 2)
siyou 回答时间:2021-8-18 14:00:45
siyou 发表于 2021-8-15 16:23
输出的PCM数据为:

有ST专家帮忙检查下上述配置是否正确吗?另外,AN5027文档和CubeMX的界面无法对应,能告知AN5027 Rev2 对应的CubeMX版本号吗?

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版