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

STM32 ADC+DMA多通道转换数据错位求助

[复制链接]
小杜杜 提问时间:2020-10-28 16:41 /
开发环境IAR7.50.2,芯片302RCT6,不知道如何解决多通道数据转化错位问题
1、需求:adc规则组采样3个通道,对ADC数据每隔不定时间处理一次,在处理函数中读取数组ConvValue[3]​,即为ADC采样的值。
2、​HAL库配置:​
        ​扫描模式使能,连续转换模式使能,DMA连续转换请求使能
3、DMA2_CH1中断不使能(目的为了减少进出中断时间)​
4、while(1)函数进入前开启dma
        HAL_ADC_Start_DMA(&hadc2,(uint32_t*)ADC2HARDWARE.ConvValue,3);
        ConvValue[3]数据类型uint16_t
5、正常情况:
        ConvValue[0]存放ADC_CH0
        ConvValue[1]存放ADC_CH1
        ConvValue[2]存放ADC_CH2
6、异常情况(非常少见)​
        ConvValue[0]存放ADC_CH2
        ​ConvValue[1]存放ADC_CH0
        ConvValue[2]存放ADC_CH1
        或者
        ConvValue[0]存放ADC_CH1
        ConvValue[1]存放ADC_CH2
        ConvValue[2]存放ADC_CH0
  1. /* ADC2 init function */
  2. static void MX_ADC2_Init(void)
  3. {

  4.   ADC_ChannelConfTypeDef sConfig;

  5.     /**Common config
  6.     */
  7.   hadc2.Instance = ADC2;
  8.   hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  9.   hadc2.Init.Resolution = ADC_RESOLUTION_12B;
  10.   hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
  11.   //hadc2.Init.ContinuousConvMode = DISABLE;
  12.   hadc2.Init.ContinuousConvMode = ENABLE;
  13.   hadc2.Init.DiscontinuousConvMode = DISABLE;
  14.   hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  15.   hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  16.   hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  17.   hadc2.Init.NbrOfConversion = 3;
  18.   //hadc2.Init.DMAContinuousRequests = DISABLE;
  19.   hadc2.Init.DMAContinuousRequests = ENABLE;
  20.   hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  21.   hadc2.Init.LowPowerAutoWait = DISABLE;
  22.   hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  23.   if (HAL_ADC_Init(&hadc2) != HAL_OK)
  24.   {
  25.     Error_Handler();
  26.   }

  27.     /**Configure Regular Channel
  28.     */
  29.   sConfig.Channel = ADC_CHANNEL_6;
  30.   sConfig.Rank = 1;
  31.   sConfig.SingleDiff = ADC_SINGLE_ENDED;
  32.   sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  33.   sConfig.OffsetNumber = ADC_OFFSET_NONE;
  34.   sConfig.Offset = 0;
  35.   if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  36.   {
  37.     Error_Handler();
  38.   }

  39.     /**Configure Regular Channel
  40.     */
  41.   sConfig.Channel = ADC_CHANNEL_8;
  42.   sConfig.Rank = 2;
  43.   if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  44.   {
  45.     Error_Handler();
  46.   }

  47.     /**Configure Regular Channel
  48.     */
  49.   sConfig.Channel = ADC_CHANNEL_12;
  50.   sConfig.Rank = 3;
  51.   if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  52.   {
  53.     Error_Handler();
  54.   }

  55. }
复制代码
  1.   else if(hadc->Instance==ADC2)
  2.   {
  3.   /* USER CODE BEGIN ADC2_MspInit 0 */

  4.   /* USER CODE END ADC2_MspInit 0 */
  5.     /* Peripheral clock enable */
  6.     HAL_RCC_ADC12_CLK_ENABLED++;
  7.     if(HAL_RCC_ADC12_CLK_ENABLED==1){
  8.       __HAL_RCC_ADC12_CLK_ENABLE();
  9.     }
  10.   
  11.     /**ADC2 GPIO Configuration   
  12.     PC0     ------> ADC2_IN6
  13.     PC2     ------> ADC2_IN8
  14.     PB2     ------> ADC2_IN12
  15.     */
  16.     GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2;
  17.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  18.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  19.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  20.     GPIO_InitStruct.Pin = GPIO_PIN_2;
  21.     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  22.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  23.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  24.     /* Peripheral DMA init*/
  25.   
  26.     hdma_adc2.Instance = DMA2_Channel1;
  27.     hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
  28.     hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
  29.     hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
  30.     hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  31.     hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  32.     //hdma_adc2.Init.Mode = DMA_NORMAL;
  33.         hdma_adc2.Init.Mode = DMA_CIRCULAR;
  34.     hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;
  35.     if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
  36.     {
  37.       Error_Handler();
  38.     }

  39.     __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc2);

  40.     /* Peripheral interrupt init */
  41.     HAL_NVIC_SetPriority(ADC1_2_IRQn, 1, 0);
  42.     HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
  43.   /* USER CODE BEGIN ADC2_MspInit 1 */

  44.   /* USER CODE END ADC2_MspInit 1 */
  45.   }
复制代码


收藏 1 评论10 发布时间:2020-10-28 16:41

举报

10个回答
caoenq 回答时间:2020-10-29 08:39:12
软件、硬件都没问题,是脑子出了问题。

评分

参与人数 1ST金币 +2 收起 理由
小杜杜 + 2 很给力!不好意思初次发帖,操作失误.

查看全部评分

ts2000 回答时间:2020-10-29 09:57:52
估计ADC转换时间太快了,DMA还没读取就覆盖了。。。 还有就是检查一下DMA的数据长度,

评分

参与人数 1ST金币 +2 收起 理由
小杜杜 + 2 很给力!

查看全部评分

小歆-2051663 回答时间:2020-10-29 11:19:22
caoenq 发表于 2020-10-29 08:39
软件、硬件都没问题,是脑子出了问题。

看问题还要付费的
数码小叶 回答时间:2020-10-29 12:45:41
初始化的顺序是啥?有没有其他地方调用了启动函数

评分

参与人数 1ST金币 +2 收起 理由
小杜杜 + 2 很给力!

查看全部评分

jcgogo 回答时间:2020-10-29 13:42:45
小杜杜 回答时间:2020-10-29 13:45:57
数码小叶 发表于 2020-10-29 12:45
初始化的顺序是啥?有没有其他地方调用了启动函数

1、先初始化DMA,再初始化ADC2,这个是STM32CUBEMX提供的。
2、然后再发起校准,最后开启DMA
  1. MX_DMA_Init();
  2. MX_ADC2_Init();
  3. HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);//ADC2校准
  4. HAL_ADC_Start_DMA(&hadc2,(uint32_t*)ADC2HARDWARE.ConvValue,3);
复制代码
小杜杜 回答时间:2020-10-29 13:48:52
ts2000 发表于 2020-10-29 09:57
估计ADC转换时间太快了,DMA还没读取就覆盖了。。。 还有就是检查一下DMA的数据长度, ...

ADC转换周期ADC_SAMPLETIME_7CYCLES_5,3个通道都一样。
DMA转换的数据长度是3,类型是Uint_16,有可能是你说的这种转换过快,DMA还没读取就覆盖了,我把转换周期变长试下
hujjj 回答时间:2020-10-29 13:56:33

也许是设置错误,准备支付金币解决问题,设置成收费了。
stm32gxx 回答时间:2020-10-29 15:06:41
利用HAL_ADC_Start_DMA这个函数,它会自动强制使能OVR中断,错位的一种可能会是overrun,建议在主程序中,在回调函数HAL_ADC_ErrorCallback中,加个while(1)来调试是否overrun了,因为初始化overrun为ADC_OVR_DATA_OVERWRITTEN,即使出现overrun,adc还会转换,数据会变化;假如设成preserved,一旦overrun,会看到adc就停止转换,数据不变
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版