你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 双ADC同步注入转换模式,模块ADC2没有数据。

[复制链接]
lzylzy1212 提问时间:2025-1-7 15:02 / 已解决

我使用的是stm32g431这款芯片,现在想采样两路模拟信号,为了采样速度更快,想用adc1和adc2两个模块分别对这两路进行采样。使用ADC_DUALMODE_INJECSIMULT(双AD同步注入模式),CUBE配置如下所示,使用定时器更新事件触发ADC注入转换。

ADC1模块配置:

1736232344955_F09FE833-FAC9-4632-8036-845807E21DAE.png

ADC2模块配置(ADC1配置了同步触发,此时ADC2配置页面中无触发源选项配置,其他与ADC1保持不变)

1736232315418_29C1AB7A-97BC-4bcc-8F21-7E38DC237B3D.png

在CUBE生成的初始化代码后添加一些ADC启动代码:

image.png

image.png

问题出现:

只有ADC1的注入通道有数据,ADC2的注入通道无数据。

image.png

想问一下这个是什么情况呢?我试过两个ADC模块都使用独立模式(ADC_MODE_INDEPENDENT),触发源与模块ADC1一致,这样是有数据的。如下:

image.png

修改的代码如下:

1736233243661_61BBA575-3E93-4550-96CE-C58A37A1251B.png

1736233300089_A8E09E0F-EBC8-4249-BA41-33007EF9DCDC.png

收藏 评论10 发布时间:2025-1-7 15:02

举报

10个回答
xmshao 最优答案 回答时间:2025-1-23 11:17:15

lzylzy1212 发表于 2025-1-22 16:09
谢谢。邮件已经收到,对比看了一下cube配置和代码,已经找到问题:</p>
<p>我的开启hadc2触发采样代码必须 ...

[md]不能简单地说 在模块初始化函数MX_ADC2_Init中就不行。

现在ADC1 ADC2是dualmode主从模同时运行,启动ADC1时 ADC2应该什么都准备好了。

所以ADC2的启动相关配置要放在ADC1的启动操作之前完成,否则就做不到同步启动。

你看我给你的示例里,启动ADC放在初始化函数外部,我非常清晰地将启动ADC2放在前面,以为你可以一眼看出端倪呢。

至于启动ADC执行代码放在哪里并无硬性规定,只需满足主从同步启动的条件即可。

具体到这里,我们可以将启动ADC1 ADC2的代码按照先执行从启动、后执行主启动的顺序放在

任何需要启动ADC的地方。

比方初始化顺序是这样:

image.png

我将启动ADC的代码放在ADC2_INIT()函数模块也照样OK.

image.png

lzylzy1212 回答时间:2025-1-7 15:04:37

使用上述配置的双ADC模式同步注入转换,CUBE生成的代码如下:(ADC2无数据)

/* ADC1 init function */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_InjectionConfTypeDef sConfigInjected = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.GainCompensation = 0;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_DUALMODE_INJECSIMULT;
  multimode.DMAAccessMode = ADC_DMAACCESSMODE_DISABLED;
  multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
  //修改为独立模式
//  multimode.Mode = ADC_MODE_INDEPENDENT;
//  multimode.DMAAccessMode = ADC_DMAACCESSMODE_DISABLED;
//  multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;
//  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
//  {
//    Error_Handler();
//  } 
  /** Configure Injected Channel
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
  sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
  sConfigInjected.InjectedOffset = 0;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.QueueInjectedContext = DISABLE;
  sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_T1_TRGO;
  sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
  sConfigInjected.InjecOversamplingMode = DISABLE;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  if(HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED) != HAL_OK )//ADC模块的自校正(单端信号)
  {
    Error_Handler();
  }
  __HAL_ADC_ENABLE_IT(&hadc1,ADC_IT_JEOC);
  HAL_ADCEx_InjectedStart(&hadc1);
  /* USER CODE END ADC1_Init 2 */

}
/* ADC2 init function */
void MX_ADC2_Init(void)
{

  /* USER CODE BEGIN ADC2_Init 0 */

  /* USER CODE END ADC2_Init 0 */

  ADC_InjectionConfTypeDef sConfigInjected = {0};

  /* USER CODE BEGIN ADC2_Init 1 */

  /* USER CODE END ADC2_Init 1 */

  /** Common config
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc2.Init.GainCompensation = 0;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.DMAContinuousRequests = DISABLE;
  hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc2.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Injected Channel
  */
  sConfigInjected.InjectedChannel = ADC_CHANNEL_2;
  sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
  sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
  sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
  sConfigInjected.InjectedOffset = 0;
  sConfigInjected.InjectedNbrOfConversion = 1;
  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
  sConfigInjected.AutoInjectedConv = DISABLE;
  sConfigInjected.QueueInjectedContext = DISABLE;
  //修改成独立模式后,手动添加以下2行触发源配置代码。
//  sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_T1_TRGO;
//  sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;  

  sConfigInjected.InjecOversamplingMode = DISABLE;
  if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */
  if(HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED) != HAL_OK )
  {
    Error_Handler();
  }
  HAL_ADCEx_InjectedStart(&hadc2);
  /* USER CODE END ADC2_Init 2 */

}
xmshao 回答时间:2025-1-7 17:05:01
我这边配置跟你基本一样,启动ADC1 ADC2的注入转换,启动定时器。


然后循环查询转换结果,没有什么问题。


   if( HAL_ADCEx_InjectedPollForConversion(&hadc1,  0xaaaa)== HAL_OK)
   {
   
   ResultADC1=  HAL_ADCEx_InjectedGetValue(&hadc1,  ADC_INJECTED_RANK_1);
   
   ResultADC2=   HAL_ADCEx_InjectedGetValue(&hadc2,  ADC_INJECTED_RANK_1);
     
      __HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_JEOS);
     
        __HAL_ADC_CLEAR_FLAG(&hadc2, ADC_FLAG_JEOS);
   
   }

rrr.png

我也是ADC1 ADC2各用1个通道,ADC1的通道信号稳定,所以结果稳定。ADC2通道悬空,结果飘动。
lzylzy1212 回答时间:2025-1-8 14:11:00

xmshao 发表于 2025-1-7 17:05
我这边配置跟你基本一样,启动ADC1 ADC2的注入转换,启动定时器。</p>
<p>

谢谢回答!

请问你用的也是G431这款芯片验证的吗?我之前有用过F407的双ADC模块同步注入,印象中没出现过问题。。

还有就是,如果你的程序中不加你写的"循环查询转换结果"代码段,只从Watch里面去看寄存器数据hadc1.Instance->JDR1和hadc1.Instance->JDR2,这两个数据是不是也应该一直在刷新呢?我的程序中没有写ADC_IT_JEOS标志位的清除语句,但我觉得这对寄存器中的数据没有影响。

xmshao 回答时间:2025-1-8 16:41:01
我也是使用STM32G474芯片,ADC这块474 和 431是一样的。


我把主循环代码 完全 屏蔽掉,只启动ADC1 /2 和TIMER,


依然可以看到结果的变化:


rrr.png




不行,你通过私信把邮件给我,我把配置给你参考下。
lzylzy1212 回答时间:2025-1-9 16:48:27

xmshao 发表于 2025-1-8 16:41
我也是使用STM32G474芯片,ADC这块474 和 431是一样的。</p>
<p>

谢谢!😄

我的邮箱:[email]1258103084@qq.com[/email]

lzylzy1212 回答时间:2025-1-22 16:09:23

xmshao 发表于 2025-1-8 16:41
我也是使用STM32G474芯片,ADC这块474 和 431是一样的。</p>
<p>

谢谢。邮件已经收到,对比看了一下cube配置和代码,已经找到问题:

我的开启hadc2触发采样代码必须要在main函数中进行初始化,在模块初始化函数MX_ADC2_Init中就不行。还不清楚是什么原因😕,但写在这边让以后遇到这种问题的人有个参考吧。

image.png

改为以下就好了:

image.png

数据可以正常刷新:

image.png

lzylzy1212 回答时间:2025-2-5 10:20:13

xmshao 发表于 2025-1-23 11:17
不能简单地说  在模块初始化函数MX_ADC2_Init中就不行。</p>
<p>现在ADC1 ADC2是dualmode主从模同时运行, ...

[md]新年好。

那我明白了,原来是这样,谢谢答复。

lzylzy1212 回答时间:2025-2-5 11:36:04

xmshao 发表于 2025-1-23 11:17
不能简单地说  在模块初始化函数MX_ADC2_Init中就不行。</p>
<p>现在ADC1 ADC2是dualmode主从模同时运行, ...

[md]刚刚试了一下,在启动ADC1之前启动ADC2是可以的。👍 👍

就是上次你邮件发给我的配置文件生成的代码中没有启动ADC的语句。是发错了吗,不然我应该会注意到这点不同的。

main函数:

fd64b1f1c02e761df748273da03608dd.png

ADC1初始化函数:

99e20412659fe2a482e78ba6517b385e.png

ADC2初始化函数:

685e1044400060bb3ae39ced5a8460db.png

xmshao 回答时间:2025-2-5 11:48:55

lzylzy1212 发表于 2025-2-5 11:36
刚刚试了一下,在启动ADC1之前启动ADC2是可以的。👍 👍</p>
<p>就是上次你邮件发给我的配置文件生成的代码 ...

[md]边实践边研究手册,搞定就好。

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版