[英]STM32: I2S input not working when using DMA
我正在尝试在 mono 设置中将“STM32F401RET6 Nucleo-64”微控制器与Adafruit I2S 麦克风接口。 为了完成这项任务,我想启用 DMA。
我使用 STM32 Cube IDE 中的设备配置工具使用以下参数激活 I2S3:
I2S3
DMA
接下来,使用代码生成器工具自动生成起始代码。 对此起始代码进行了一些更改:
我已经使用示波器对来自麦克风的数字数据波形进行了 plot。 这似乎是正确的,即声音触发了麦克风,这在最高有效位中是可见的。 如果我是正确的,这使得错误在于将数据读入正确的格式。 要执行 mono 测量,数据表指出应该使用 100k Ohm 电阻器,该电阻器存在于我的设置中。
在我的 main.c 程序中,我正在使用 HAL function ' HAL_I2S_Receive_DMA ' 来尝试填充我的 500 个样本数组。
main.c:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
I2S_HandleTypeDef hi2s3;
DMA_HandleTypeDef hdma_spi3_rx;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2S3_Init(void);
static void MX_DMA_Init(void);
int main(void)
{
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2S3_Init();
MX_DMA_Init();
/* Infinite loop */
HAL_StatusTypeDef retval; // return value
volatile int16_t data[500] = {0};
int16_t data_shifted[500];
while (1)
{
retval = HAL_I2S_Receive_DMA(&hi2s3, data, 500);
// for(short i=0; i<500; i++){
// data_shifted[i] = data[i] >> 14;
// }
HAL_Delay(1000);
}
}
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_SCALE2);
/* Initializes the RCC Oscillators according to the specified parameters
in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 84;
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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2S3_Init(void)
{
hi2s3.Instance = SPI3;
hi2s3.Init.Mode = I2S_MODE_MASTER_RX;
hi2s3.Init.Standard = I2S_STANDARD_MSB;
hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K;
hi2s3.Init.CPOL = I2S_CPOL_LOW;
hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_ENABLE;
if (HAL_I2S_Init(&hi2s3) != HAL_OK)
{
Error_Handler();
}
}
// Enable DMA controller clock
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
}
/*GPIO Initialization Function */
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
}
/* This function is executed in case of error occurrence. */
void Error_Handler(void)
{
/* Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
/**
Reports the name of the source file and the source line number
where the assert_param error has occurred.
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* 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) */
}
#endif /* USE_FULL_ASSERT */
当我调试代码并在“main.c”的第 34 行设置断点时,微控制器 memory 不会相应地更新其值。 所有值都保持为零。 两个 DMA 状态标志都设置为 1。我猜这个问题与时间有关,但直到现在我才能解决这个问题。
链接到 GitHub 上的 HAL_I2S_Receive_DMA function
提前致谢。
DMA 必须在 ADC 外设之前初始化,但生成的代码以错误的顺序执行初始化。 众所周知,当前 STM32CubeIDE 的默认配置存在小缺陷。 尝试改变
MX_GPIO_Init();
MX_I2S3_Init();
MX_DMA_Init(); // wrong order
至
MX_GPIO_Init();
MX_DMA_Init(); // right order
MX_I2S3_Init();
要进行永久性更改,
以我的经验,
HAL_I2S_Receive_DMA() function 是配置地址(如果学LL API,需要手动设置源/目的地址和数据长度:[LL_DMA_SetDataLength()])
因此,您可以在 While(1) 循环之前移动它。
如果要读取/处理缓冲区“数据”,可以使用 dma 中断回调 function,在 HAL API 中为:HAL_I2S_RxHalfCpltCallback(), HAL_I2S_RxCpltCallback()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.