其他分享
首页 > 其他分享> > STM32CubeMX ADC多通道DMA(循环传输Circular,单次Normal)

STM32CubeMX ADC多通道DMA(循环传输Circular,单次Normal)

作者:互联网

Cube配置
在这里插入图片描述
代码

uint16_t AD_Value[20];
//main.c文件
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);

上面配置如果是word,则更改一下定义就好了,cube生成的代码会随着变:

uint32_t AD_Value[20];
//main.c文件
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);

分析一下函数原型

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)

有网友就简单看到原型是uint32_t就认为必须是32位了,其实ad只有12位,数据定义成16位才是物尽其用。产生这个试验想法是基于std库用过一次就是16位的,另外uint16_t AD_Value[20]也可以换成二维数组uint16_t AD_Value[10][2],二者本质没什么区别,好处是通道更多了就只需要改变第二个下标就行了,再其他地方处理AD数据的时候也很方便。
采样的数据:
在这里插入图片描述
再来看看normal模式吧(调试遇到问题了)
代码如下

/* USER CODE BEGIN 0 */
uint16_t AD_Value[20];
uint8_t Rec_Flag;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	Rec_Flag=1;
}
/* 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_ADC1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(Rec_Flag==1)
		{
			Rec_Flag=0;
			HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
		}
		HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

在这里插入图片描述
补贴:
Normal模式下,结果多次尝试,最终解决了
讨论一下单次传输的好处:DMA传输的时候如果读取内存片段,会有仲裁器的问题,在以前做过FFT的例子中,需要获取一个连续间隔的AD,如取1024点,假设前面的500个点是DMA刚传输的,而后面的点是上个时刻的数据,电压数据导出到excel显示波形就有断点,但这并不影响FFT本身,前后是循环是接在一起的,出现误差的影响的是恰好500这个点会有时钟偏差(影响不太大,最多一个时钟周期,可查阅相关数据手册)。采集直流信号二者无差别!
加了一句关闭DMA的语句,更改后代码如下

/* USER CODE BEGIN 0 */
uint16_t AD_Value[20];
uint8_t Rec_Flag;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	Rec_Flag=1;
}
/* 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_ADC1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(Rec_Flag==1)
		{
			Rec_Flag=0;
			HAL_ADC_Stop_DMA(&hadc1);
			HAL_ADC_Start_DMA(&hadc1,(uint32_t *)AD_Value,20);
		}
		HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

欢迎交流,Q:cqkz52@qq.com

标签:DMA,CODE,HAL,AD,Normal,多通道,USER,END
来源: https://blog.csdn.net/qq_33044119/article/details/106991079