STM32 CubeMx ADC DMA 方式实现多路采集 配置实例 [已验证]



先上结果图,DMA方式多路采集ADC数据并打印Count值和电压:
在这里插入图片描述

1、选择ADC1/ADC2的channel:

进入正文:打开CubeMX工程,选择好芯片时钟,然后开始配置ADC & DMA:
根据具体需要,这里举例选择ADC1的IN6 - IN9
在这里插入图片描述

2、配置ADC Setting参数:

在parameter settings中,主要配置ADC多路采集参数:

  • Mode 模式:独立采集
  • Scan Conversion Mode 扫描模式 :ENABLE
  • Continuous Conversion Mode 连续转换模式:ENABLE

在这里插入图片描述

3、配置多路通道采集及顺序

配置有多少路ADC,这里是IN6-IN9,共4路
在这里插入图片描述

根据RANK1-4 配置采集顺序:其余保持默认
在这里插入图片描述

4、配置DMA

在ADC Configuration 参数选择DMA Settings, 点击Add,然后选择所用的ADC:

在这里插入图片描述
然后,针对ADC1对应的DMAChannel 1,

  • 配置下DMA模式为Circular,既循环更新数据,否则默认的Normal模式触发后只执行 一次,
  • 配置自增地址为Memory方式,并选择word或half word,这里选择word,是因为我程序里定义uint32_t 的数组来存储多路ADC数据的,占用四个字节既选择word

在这里插入图片描述

  • 生成代码前要检查下时钟配置是否正常:

ADC Prescaler 这里为6,时钟为12M,最大不能超出14M
在这里插入图片描述

5、生成代码,修改代码:

  • Generate code后,在定义一个全局数组给到DMA来存储ADC多路数据,

例如:
uint32_t ADC1_Value_DMA[4];
在这里插入图片描述

  • 在使用之前,需要start DMA传输,这里在main() 初始化ADC之后就开始,加入代码:

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC1_Value_DMA, 4);

这里的最后一次参数4是代表有4路
在这里插入图片描述

  • 还需要把DMA的中断注释掉,否则会一直进中断,因为我用了FreeRTOS,如果不注释会导致FreeRTOS运行异常,感觉这里DMA中断其实没有啥用,因为数据已经配置好了会实时更新到memory里,但CubeMx默认给Enable

在这里插入图片描述

6、使用DMA传输的ADC数据:

这样Debug运行起来,DMA就会不断的往ADC1_Value_DMA[]数组中更新RANK1-RANK4,既ADC1 IN6-IN9的采样数据,

可以增加log 代码 ,Debug打印出来,或live watch里查看:

      float Channel_6 = (float)(ADC1_Value_DMA[0]&0xFFF)*3.3/4096;
      float Channel_7 = (float)(ADC1_Value_DMA[1]&0xFFF)*3.3/4096;
      float Channel_8 = (float)(ADC1_Value_DMA[2]&0xFFF)*3.3/4096;
      float Channel_9 = (float)(ADC1_Value_DMA[3]&0xFFF)*3.3/4096;

      printf("Star measure ADC1 channel 6-9\r\n");
      printf("ADC1 Channel_6 Count: %d,   voltage: %f \r\n",ADC1_Value_DMA[0],Channel_6);
      printf("ADC1 Channel_7 Count: %d,   voltage:  %f \r\n",ADC1_Value_DMA[1], Channel_7);
      printf("ADC1 Channel_8 Count: %d,   voltage:  %f \r\n",ADC1_Value_DMA[2], Channel_8);
      printf("ADC1 Channel_9 Count: %d,   voltage:  %f \r\n",ADC1_Value_DMA[3], Channel_9);
    

在这里插入图片描述

附ADC初始化函数作为参考:

static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 4;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = ADC_REGULAR_RANK_4;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

博主热门文章推荐:

一篇读懂系列:

LoRa Mesh系列:

网络安全系列:

嵌入式开发系列:

AI / 机器学习系列:


在这里插入图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HowieXue

求打赏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值