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

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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版