小杜杜 发表于 2020-10-28 16:41:28

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

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

ADC_ChannelConfTypeDef sConfig;

    /**Common config
    */
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
//hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.ContinuousConvMode = ENABLE;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 3;
//hadc2.Init.DMAContinuousRequests = DISABLE;
hadc2.Init.DMAContinuousRequests = ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
    Error_Handler();
}

    /**Configure Regular Channel
    */
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = 1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
    Error_Handler();
}

    /**Configure Regular Channel
    */
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
    Error_Handler();
}

    /**Configure Regular Channel
    */
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = 3;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
    Error_Handler();
}

}else if(hadc->Instance==ADC2)
{
/* USER CODE BEGIN ADC2_MspInit 0 */

/* USER CODE END ADC2_MspInit 0 */
    /* Peripheral clock enable */
    HAL_RCC_ADC12_CLK_ENABLED++;
    if(HAL_RCC_ADC12_CLK_ENABLED==1){
      __HAL_RCC_ADC12_CLK_ENABLE();
    }

    /**ADC2 GPIO Configuration   
    PC0   ------> ADC2_IN6
    PC2   ------> ADC2_IN8
    PB2   ------> ADC2_IN12
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

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

    /* Peripheral DMA init*/

    hdma_adc2.Instance = DMA2_Channel1;
    hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    //hdma_adc2.Init.Mode = DMA_NORMAL;
        hdma_adc2.Init.Mode = DMA_CIRCULAR;
    hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc2);

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(ADC1_2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
/* USER CODE BEGIN ADC2_MspInit 1 */

/* USER CODE END ADC2_MspInit 1 */
}

caoenq 发表于 2020-10-29 08:39:12

软件、硬件都没问题,是脑子出了问题。

ts2000 发表于 2020-10-29 09:57:52

估计ADC转换时间太快了,DMA还没读取就覆盖了。。。 还有就是检查一下DMA的数据长度,

小歆-2051663 发表于 2020-10-29 11:19:22

caoenq 发表于 2020-10-29 08:39
软件、硬件都没问题,是脑子出了问题。

看问题还要付费的:D:D:D

数码小叶 发表于 2020-10-29 12:45:41

初始化的顺序是啥?有没有其他地方调用了启动函数:D:D:D

jcgogo 发表于 2020-10-29 13:42:45

:D:D:D:D

小杜杜 发表于 2020-10-29 13:45:57

数码小叶 发表于 2020-10-29 12:45
初始化的顺序是啥?有没有其他地方调用了启动函数

1、先初始化DMA,再初始化ADC2,这个是STM32CUBEMX提供的。
2、然后再发起校准,最后开启DMA
MX_DMA_Init();
MX_ADC2_Init();
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);//ADC2校准
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

小歆-2051663 发表于 2020-10-29 11:19
看问题还要付费的

也许是设置错误,准备支付金币解决问题,设置成收费了。

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就停止转换,数据不变
页: [1] 2
查看完整版本: STM32 ADC+DMA多通道转换数据错位求助