数字麦克风PDM信号采集与STM32 I2S接口应用(四)--单片机源码

本文是数字麦克风笔记文章的单片机程序。一些朋友私信我,调试出问题。

我的博客只是总结经验不是教程,所以不是什么都记,想起来当时我也是花了一些时间才发现问题的,可能确实有些坑。

我就把源码贴出来吧,可能主要问题是DMA的配置。尤其双DMA时候,需要手动启动I2S的接收DMA,HAL库没有这个接口,不看datasheet是找不到这个毛病的,这也是HAL库用多了引起的问题,一些特底层的问题大家都不愿意去搞了。

测试代码有点乱没整理。

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "crc.h"
#include "dma.h"
#include "i2s.h"
//#include "pdm2pcm.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
#include <stdio.h>
#include "pdm_filter.h"
#include "arm_math.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/*
---- 12khz
% Discrete-Time IIR Filter (real)                           
% -------------------------------                           
% Filter Structure    : Direct-Form I, Second-Order Sections
% Number of Sections  : 3                                   
% Stable              : Yes                                 
% Linear Phase        : No                                  

                                                           
SOS Matrix:                                                 
1  -2  1  1  1.195433962890738    0.69059892324149696       
1  -2  1  1  0.94280904158206325  0.33333333333333331       
1  -2  1  1  0.84028692165132668  0.18834516088404465       
                                                            
Scale Values:                                               
0.12379124008768976                                         
0.097631072937817504                                        
0.087014559808179473   


--- 2khz
% Generated by MATLAB(R) 8.3 and the Signal Processing Toolbox 6.21.
% Generated on: 23-Jul-2019 18:13:58

% Coefficient Format: Decimal

% Discrete-Time IIR Filter (real)                           
% -------------------------------                           
% Filter Structure    : Direct-Form I, Second-Order Sections
% Number of Sections  : 3                                   
% Stable              : Yes                                 
% Linear Phase        : No                                  

                                                           
SOS Matrix:                                                 
1  -2  1  1  -1.6812394272942188  0.81976044292731376       
1  -2  1  1  -1.454243586251585   0.57406191508395488       
1  -2  1  1  -1.349079994888392   0.46023366403769816       
                                                            
Scale Values:                                               
0.8752499675553832                                          
0.75707637533388505                                         
0.70232841473152252                                         
*/

#define numStages  3 // 6 order                 
#define FILTER_SAMPLES  2*160    
float32_t FilterDataIn[FILTER_SAMPLES]={0};
float32_t FilterDataOut[FILTER_SAMPLES]={0};

static float32_t testInput_f32_50Hz_200Hz[FILTER_SAMPLES]; /* input samping points */
static float32_t testOutput[FILTER_SAMPLES];               /* output  */
static float32_t IIRStateF32[4*numStages];                      /*  tmp buf=numTaps + blockSize - 1*/
                                                                             
#if 1 // 12khz hpf                                                                                                                                        
const float32_t IIRCoeffs32HP[5*numStages] = {
1.0f,  -2.0f,  1.0f,  -1.195433962890738f,    -0.69059892324149696f,        
1.0f,  -2.0f,  1.0f,  -0.94280904158206325f,  -0.33333333333333331f, 
1.0f,  -2.0f,  1.0f,  -0.84028692165132668f,  -0.18834516088404465f  
};
const float32_t ScaleValue  = 0.12379124008768976f  * 0.097631072937817504f * 0.087014559808179473f;
#else  // 2khz hpf, people can hear the sound, just high pitch.
const float32_t IIRCoeffs32HP[5*numStages] = {
1.0f,  -2.0f,  1.0f,  1.6812394272942188,  -0.81976044292731376,        
1.0f,  -2.0f,  1.0f,  1.454243586251585,   -0.57406191508395488, 
1.0f,  -2.0f,  1.0f,  1.349079994888392,   -0.46023366403769816  
};
const float32_t ScaleValue  = 0.8752499675553832f  * 0.75707637533388505f * 0.70232841473152252f;
#endif


void arm_copy_u162f32(
  int16_t * pSrc,
  float32_t * pDst,
  uint32_t blockSize)
{
  uint32_t blkCnt;                               /* loop counter */

#ifndef ARM_MATH_CM0

  /* Run the below code for Cortex-M4 and Cortex-M3 */

  /*loop Unrolling */
  blkCnt = blockSize >> 2u;

  /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
   ** a second loop below computes the remaining 1 to 3 samples. */
  while(blkCnt > 0u)
  {
    /* C = A */
    /* Copy and then store the results in the destination buffer */
    *pDst++ = *pSrc++;
    *pDst++ = *pSrc++;
    *pDst++ = *pSrc++;
    *pDst++ = *pSrc++;

    /* Decrement the loop counter */
    blkCnt--;
  }

  /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
   ** No loop unrolling is used. */
  blkCnt = blockSize % 0x4u;

#else

  /* Run the below code for Cortex-M0 */

  /* Loop over blockSize number of values */
  blkCnt = blockSize;

#endif /* #ifndef ARM_MATH_CM0 */

  while(blkCnt > 0u)
  {
    /* C = A */
    /* Copy and then store the results in the destination buffer */
    *pDst++ = *pSrc++;

    /* Decrement the loop counter */
    blkCnt--;
  }
}


void arm_copy_f322u16(
  float32_t * pSrc,
  int16_t * pDst,
  uint32_t blockSize)
{
  uint32_t blkCnt;                               /* loop counter */

#ifndef ARM_MATH_CM0

  /* Run the below code for Cortex-M4 and Cortex-M3 */

  /*loop Unrolling */
  blkCnt = blockSize >> 2u;

  /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
   ** a second loop below computes the remaining 1 to 3 samples. */
  while(blkCnt > 0u)
  {
    /* C = A */
    /* Copy and then store the results in the destination buffer */
    *pDst++ = (int16_t)*pSrc++;
    *pDst++ = (int16_t)*pSrc++;
    *pDst++ = (int16_t)*pSrc++;
    *pDst++ = (int16_t)*pSrc++;

    /* Decrement the loop counter */
    blkCnt--;
  }

  /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
   ** No loop unrolling is used. */
  blkCnt = blockSize % 0x4u;

#else

  /* Run the below code for Cortex-M0 */

  /* Loop over blockSize number of values */
  blkCnt = blockSize;

#endif /* #ifndef ARM_MATH_CM0 */

  while(blkCnt > 0u)
  {
    /* C = A */
    /* Copy and then store the results in the destination buffer */
    *pDst++ = (int16_t)*pSrc++;

    /* Decrement the loop counter */
    blkCnt--;
  }
}

/* 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 ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#define PDM_2_PCM_SAM  (2*64)
#define PDM_SAM_POINTS  (2*640)
#define PCM_SAM_POINTS  (2*160)
typedef struct {
   int pdmIdx;
   int pcmIdx;
   uint16_t PDMBuf[2][PDM_SAM_POINTS];
   int16_t PCMBuf[PCM_SAM_POINTS];
}MicrophoneBufStruct;

MicrophoneBufStruct MicrophoreBuf = {0};
PDMFilter_InitStruct Filter;

void HAL_I2S_DMA_RxM0CpltCallback(DMA_HandleTypeDef *hdma);
void HAL_I2S_DMA_RxM1CpltCallback(DMA_HandleTypeDef *hdma);
void HAL_I2S_DMA_Rx_Error_CpltCallback(DMA_HandleTypeDef *hdma);
int UsbTxErr = 0;
uint8_t printBuf[PCM_SAM_POINTS*10]={0};
int tests = 0;


static int32_t idx = 0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2S2_Init();
  MX_USB_DEVICE_Init();
  MX_CRC_Init();
//  MX_PDM2PCM_Init();
  /* USER CODE BEGIN 2 */
   HAL_Delay(3000);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    __HAL_RCC_GPIOB_CLK_ENABLE();
    //PB0 : FOR MEAS IIS SAMPING TIME
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 0);
  
  /* Filter LP & HP Init */ //Õâ¸öÂ˲¨Æ÷Ч¹û±È½Ï²î£¬×Ô¼ºÂ˲¨²ÅÐУ¬³öÏÖÔëÉùºÍÌø±ä¡£
    Filter.HP_HZ = 100; 
    Filter.LP_HZ = 15000;
    Filter.Fs = 32000;
    Filter.Out_MicChannels = 1;
    Filter.In_MicChannels = 1;
    PDM_Filter_Init((PDMFilter_InitStruct *)&Filter);
    
    hi2s2.hdmarx->XferCpltCallback = HAL_I2S_DMA_RxM0CpltCallback;
    hi2s2.hdmarx->XferM1CpltCallback = HAL_I2S_DMA_RxM1CpltCallback;
    hi2s2.hdmarx->XferErrorCallback = HAL_I2S_DMA_Rx_Error_CpltCallback;
    HAL_DMAEx_MultiBufferStart_IT(hi2s2.hdmarx, (uint32_t)&hi2s2.Instance->DR, 
                                  (uint32_t)&MicrophoreBuf.PDMBuf[0], (uint32_t)&MicrophoreBuf.PDMBuf[1], PDM_SAM_POINTS);
    HAL_I2S_DMAResume(&hi2s2);
    /* Enable Rx DMA Request */
    SET_BIT(hi2s2.Instance->CR2, SPI_CR2_RXDMAEN);
    
//    HAL_I2S_Receive_DMA (&hi2s2, MicrophoreBuf.PDMBuf[0], PDM_SAM_POINTS);
    static char printBuf[100]={0};
    static int cur_buf = 0;
    HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 0);
    
    arm_biquad_casd_df1_inst_f32 S = {0};
    arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32HP[0], (float32_t *)&IIRStateF32[0]);
    while (1)
    {
        uint16_t *srcBuf = 0;
        int16_t *dstBuf = 0;
      
      
         if(MicrophoreBuf.pdmIdx == -1) continue;
          
          dstBuf = MicrophoreBuf.PCMBuf;
      
          srcBuf = MicrophoreBuf.PDMBuf[MicrophoreBuf.pdmIdx]; 
          MicrophoreBuf.pdmIdx = -1;      
          for(int i=0; i<PDM_SAM_POINTS; i++)
          {
            uint16_t a = srcBuf[i];
            srcBuf[i] = HTONS(a);
          }
          uint16_t volumeGain = 10;
          int num = 0;
          
           HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 1);
          for(int i=0; i<PDM_SAM_POINTS; i=i+PDM_2_PCM_SAM)
          {
            num += PDM_Filter_64_LSB((uint8_t *)&srcBuf[i], (uint16_t *)&dstBuf[i/4], volumeGain , (PDMFilter_InitStruct *)&Filter);
          }
           HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 0);

          // USE IIR FILTER HERE
       #if 1
          //HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 1);
          arm_copy_u162f32(dstBuf, FilterDataIn, FILTER_SAMPLES);
          arm_biquad_cascade_df1_f32(&S, FilterDataIn, FilterDataOut, FILTER_SAMPLES);
          arm_scale_f32(FilterDataOut, ScaleValue, FilterDataOut, FILTER_SAMPLES);
          arm_copy_f322u16(FilterDataOut, dstBuf, FILTER_SAMPLES);
          //HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 0);
        #endif
                  
       #if 0 // send raw data to pc
          if(USBD_OK != CDC_Transmit_FS((uint8_t *)dstBuf,  2*PCM_SAM_POINTS) )
          {
              UsbTxErr++;
//               HAL_Delay(1);
//               CDC_Transmit_FS((uint8_t *)dstBuf,  PCM_SAM_POINTS);
          }
        #endif  
          
          
        #if 1 // calc fire trigger.
          float32_t calcRst = 0.0f;
          uint8_t triggerFired = 0;
          HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 1);
          for(int i=0; i<2; i++)
          {
            int offset = i*FILTER_SAMPLES/2;
            arm_abs_f32(FilterDataOut + offset, FilterDataOut + offset, FILTER_SAMPLES/2);
            arm_mean_f32(FilterDataOut+ offset, FILTER_SAMPLES/2, &calcRst);
            if(((int)calcRst >1700) && (triggerFired == 0))
            {
               triggerFired = 1;
               break;
            }
          }
          HAL_GPIO_WritePin( GPIOB, GPIO_PIN_0, 0);
          uint8_t cmd[] = { 2,0,0,0,  
                            0,0,0,0,  
                            3,0,0,0,  1, 6,7};
          cmd[12] = triggerFired<<7; // 0x80 null, 0x81 sound, 0x82 acc, 0x83 all.
          cmd[13] = (uint8_t)(((int)calcRst) & 0xff);    
          cmd[14] = (uint8_t)(((int)calcRst) >> 8);                              
          if(USBD_OK != CDC_Transmit_FS((uint8_t *)cmd,  sizeof(cmd) ) )
          {
              UsbTxErr++;
          }

         #endif
          

        
      }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      
    /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  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 = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses 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();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
  PeriphClkInitStruct.PLLI2S.PLLI2SN = 369;
  PeriphClkInitStruct.PLLI2S.PLLI2SR = 6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  /* Clear DBM bit */
  hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);

  /* Configure DMA Stream data length */
  hdma->Instance->NDTR = DataLength;

  /* Memory to Peripheral */
  if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
  {
    /* Configure DMA Stream destination address */
    hdma->Instance->PAR = DstAddress;

    /* Configure DMA Stream source address */
    hdma->Instance->M0AR = SrcAddress;
  }
  /* Peripheral to Memory */
  else
  {
    /* Configure DMA Stream source address */
    hdma->Instance->PAR = SrcAddress;

    /* Configure DMA Stream destination address */
    hdma->Instance->M0AR = DstAddress;
  }
}

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
  uint16_t *srcBuf = MicrophoreBuf.PDMBuf[0];
  int16_t *dstBuf = MicrophoreBuf.PCMBuf;
  
//  HAL_I2S_Receive_DMA (&hi2s2, MicrophoreBuf.PDMBuf[0], PDM_SAM_POINTS);
  
//  if(idx == 0){
//    MicrophoreBuf.pdmIdx = 0;
//    //HAL_I2S_Receive_DMA (&hi2s2, (uint16_t*)MicrophoreBuf.PDMBuf[1], PDM_SAM_POINTS);
//  }
//  else if(idx % 2 == 1){
//    MicrophoreBuf.pdmIdx = 1;
//   // HAL_I2S_Receive_DMA (&hi2s2, (uint16_t*)MicrophoreBuf.PDMBuf[0], PDM_SAM_POINTS);
//  }
//  else{
//    MicrophoreBuf.pdmIdx = 0;
//   // HAL_I2S_Receive_DMA (&hi2s2, (uint16_t*)MicrophoreBuf.PDMBuf[1], PDM_SAM_POINTS);
//  }
//  idx++;
}

void HAL_I2S_DMA_RxM0CpltCallback(DMA_HandleTypeDef *hdma)
{
  MicrophoreBuf.pdmIdx = 0;
}


void HAL_I2S_DMA_RxM1CpltCallback(DMA_HandleTypeDef *hdma)
{
  MicrophoreBuf.pdmIdx = 1;
}

void HAL_I2S_DMA_Rx_Error_CpltCallback(DMA_HandleTypeDef *hdma)
{

}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
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,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
View Code
/**
  ******************************************************************************
  * File Name          : I2S.c
  * Description        : This file provides code for the configuration
  *                      of the I2S instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "i2s.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

I2S_HandleTypeDef hi2s2;
DMA_HandleTypeDef hdma_spi2_rx;

/* I2S2 init function */
void MX_I2S2_Init(void)
{

  hi2s2.Instance = SPI2;
  hi2s2.Init.Mode = I2S_MODE_MASTER_RX;
  hi2s2.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
  hi2s2.Init.AudioFreq = 64000;//I2S_AUDIOFREQ_32K;
  hi2s2.Init.CPOL = I2S_CPOL_HIGH;//I2S_CPOL_LOW;
  hi2s2.Init.ClockSource = I2S_CLOCK_PLL;
  hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
  if (HAL_I2S_Init(&hi2s2) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_I2S_MspInit(I2S_HandleTypeDef* i2sHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(i2sHandle->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspInit 0 */

  /* USER CODE END SPI2_MspInit 0 */
    /* I2S2 clock enable */
    __HAL_RCC_SPI2_CLK_ENABLE();
  
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2S2 GPIO Configuration    
    PC3     ------> I2S2_SD
    PB10     ------> I2S2_CK
    PB12     ------> I2S2_WS 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* I2S2 DMA Init */
    /* SPI2_RX Init */
    hdma_spi2_rx.Instance = DMA1_Stream3;
    hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;//DMA_PDATAALIGN_HALFWORD;
    hdma_spi2_rx.Init.Mode =  DMA_CIRCULAR;
    //hdma_spi2_rx.Init.Mode =  DMA_NORMAL;
    hdma_spi2_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi2_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(i2sHandle,hdmarx,hdma_spi2_rx);

  /* USER CODE BEGIN SPI2_MspInit 1 */
    
  /* USER CODE END SPI2_MspInit 1 */
  }
}

void HAL_I2S_MspDeInit(I2S_HandleTypeDef* i2sHandle)
{

  if(i2sHandle->Instance==SPI2)
  {
  /* USER CODE BEGIN SPI2_MspDeInit 0 */

  /* USER CODE END SPI2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_SPI2_CLK_DISABLE();
  
    /**I2S2 GPIO Configuration    
    PC3     ------> I2S2_SD
    PB10     ------> I2S2_CK
    PB12     ------> I2S2_WS 
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_3);

    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_12);

    /* I2S2 DMA DeInit */
    HAL_DMA_DeInit(i2sHandle->hdmarx);
  /* USER CODE BEGIN SPI2_MspDeInit 1 */

  /* USER CODE END SPI2_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
View Code

 

 


 

数字麦克风PDM信号采集与STM32 I2S接口应用--笔记目录:

数字麦克风PDM信号采集与STM32 I2S接口应用(一)

https://www.cnblogs.com/pingwen/p/11298675.html

数字麦克风PDM信号采集与STM32 I2S接口应用(二)

https://www.cnblogs.com/pingwen/p/11301935.html

数字麦克风PDM信号采集与STM32 I2S接口应用(三)

https://www.cnblogs.com/pingwen/p/11794081.html

数字麦克风PDM转PCM与STM32 I2S接口应用----重要文档列表

https://www.cnblogs.com/pingwen/p/11302452.html

数字麦克风PDM信号采集与STM32 I2S接口应用(四)--单片机源码

https://www.cnblogs.com/pingwen/p/13371144.html

posted on 2020-07-24 11:47  啊哈彭  阅读(983)  评论(0编辑  收藏

导航