STM32L151 多通道ADC DMA循环扫描STM32CubeIDE STM32CubeMX参考设计

时间:2024-10-15 08:09:44

简介

项目开发过程中,采用STM32L151 芯片进行涉及,其中需要使用其片上ADC进行多路ADC数据采样。这里就记录一下实际这块的开发过程,其中涉及工程代码再项目中实际投产使用。STM32L151 多通道ADC DMA循环扫描STM32CubeIDE STM32CubeMX参考设计。

 本文使用工程下载

STM32L151多通道ADCDMA循环扫描STM32CubeIDESTM32CubeMX参考设计资源-****文库

设计思路

由于需要采样11路ADC电压,所以采用DMA的方式,并设置ADC循环扫描,来减轻CPU的工作负担。采用STM32CubeIDE、STM32CubeMX+Keil uVision5进行设计验证。

调试过程关键问题

刚开始开发采用STM32CubeIDE,由于版本较低,出现了一个比较难搞的问题,后面切换到STM32CubeMX+Keil uVision5进行开发。该问题记录在博客,有兴趣的同学可以了解一下STM32CubeIDE使用ADC采用DMA重大BUG-****博客

是否需要打开ADC中断?

我看了很多网上的设计,都没有说清楚这个问题。这里其实没有必要打开ADC中断了,因为已经有使用DMA了,DMA传输完成后会给出DMA中断。如果有需要,可以在DMA中断处理函数,进行处理。

void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */

  /* USER CODE END DMA1_Channel1_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc);
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */

  /* USER CODE END DMA1_Channel1_IRQn 1 */
}

硬件设计

时钟方面,使能外部8Mhz时钟,时钟配置图如下图所示,从图中可以看出ADC的时钟是由内部高速时钟提供的。

ADC设计,如下图所示,打开11路ADC采样通道。

软件设计

 串口打印设置

添加串口打印宏定义如下:

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
//#if (DEBUG_PRINTF_ON == 1)
    //HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1 , 0xffff);
	while((USART1->SR&0x40)==0){};
		USART1->DR = ch;
//	while((USART3->SR&0x40)==0);
//		USART3->DR = ch;
//#endif
    return ch;
}

这里需要提醒的是采用STM32CubeMX+Keil uVision5进行设计的时候,因为使用了printf函数,所以需要将工程的如下设置勾选。

ADC初始化

 ADC初始配置如下代码所示,这里针对hadc.Init.ContinuousConvMode = DISABLE;由于DMA数据深度设置为1,也就是说11路采样数据采样完成后,就有DMA中断,所以DMA中断太频繁,如果设置hadc.Init.ContinuousConvMode = ENABLE;会导致MCU一直处于DMA中断中,这里也可以加深DMA采样数据来解决这个问题,由于本项目需求较为简单,就是对采样率没有特别要求。所以无需加深DMA的采样数据。ADC如果采样数据不对,可以尝试调大单个通道sConfig.SamplingTime = ADC_SAMPLETIME_96CYCLES;来进行调试。

hadc.Instance = ADC1;
  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE;
  hadc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE;
  hadc.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
  hadc.Init.ContinuousConvMode = DISABLE;
  hadc.Init.NbrOfConversion = 11;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.DMAContinuousRequests = ENABLE;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_96CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = ADC_REGULAR_RANK_5;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_6;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_7;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_18;
  sConfig.Rank = ADC_REGULAR_RANK_8;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_19;
  sConfig.Rank = ADC_REGULAR_RANK_9;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_20;
  sConfig.Rank = ADC_REGULAR_RANK_10;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_21;
  sConfig.Rank = ADC_REGULAR_RANK_11;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

 调试记录

STM32CubeIDE 1.7.0工程测试记录:

STM32CubeMX 6.8.1+Keil uVision5测试记录

本文使用工程下载

STM32L151多通道ADCDMA循环扫描STM32CubeIDESTM32CubeMX参考设计资源-****文库