STM32F767 ADC多通道+DMA采集

2019-07-20 01:30发布

目的:通过DMA实现ADC1的通道1、2、3电压采集,对三个通道连续采集10次,采集的数据储存于一个二维数组中u16 uhADCxConvertedValue[10][3]。
现象:实际采集时,数组的前4个元素仅更新一次后不再更新,后面的数据可以正常更新,仿真结果如图:
微信图片_20180524164550.png    DMA设置的memaddr跟数组地址是一致的,但是前4个数据不会更新。如果用一维数组u16 uhADCxConvertedValue[3]储存三个通道的数据就完全不更新了。贴出代码,求大佬们解答。

ADC配置代码如下:

/* ADC handler declaration */
ADC_HandleTypeDef    AdcHandle;
/* Variable used to get converted value */
u16 uhADCxConvertedValue[10][3] = {0};

void bsp_ADC_Init(void)
{
        ADC_ChannelConfTypeDef sConfig;
       
        /*##-1- Configure the ADC peripheral #######################################*/
        AdcHandle.Instance                           = ADC1;
        AdcHandle.Init.ClockPrescaler        = ADC_CLOCKPRESCALER_PCLK_DIV4;
        AdcHandle.Init.Resolution            = ADC_RESOLUTION_12B;
        AdcHandle.Init.ScanConvMode          = ENABLE;                        /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
        AdcHandle.Init.ContinuousConvMode    = ENABLE;                        /* Continuous mode disabled to have only 1 conversion at each conversion trig */
        AdcHandle.Init.DiscontinuousConvMode = DISABLE;                       /* Parameter discarded because sequencer is disabled */
        AdcHandle.Init.NbrOfDiscConversion   = 0;
        AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;        /* Conversion start trigged at each external event */
        AdcHandle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
        AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
        AdcHandle.Init.NbrOfConversion       = 3;
        AdcHandle.Init.DMAContinuousRequests = ENABLE;
        AdcHandle.Init.EOCSelection          = DISABLE;
       
        HAL_ADC_Init(&AdcHandle);
       
        /*##-2- Configure ADC regular channel ######################################*/
    sConfig.Channel      = ADC_CHANNEL_1;
    sConfig.Rank         = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;  
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
       
    sConfig.Channel      = ADC_CHANNEL_2;
    sConfig.Rank         = 2;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

    sConfig.Channel      = ADC_CHANNEL_3;
    sConfig.Rank         = 3;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    sConfig.Offset       = 0;
    HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);

    HAL_ADC_Start_DMA(&AdcHandle,(u32*)uhADCxConvertedValue,30);
}


/**
  * @brief ADC MSP Initialization
  *        This function configures the hardware resources used in this example:
  *           - Peripheral's clock enable
  *           - Peripheral's GPIO Configuration
  * @param hadc: ADC handle pointer
  * @retval None
  */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
  GPIO_InitTypeDef          GPIO_InitStruct;
  static DMA_HandleTypeDef  hdma_adc;

  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* ADC1 Periph clock enable */
  __HAL_RCC_ADC1_CLK_ENABLE();
  /* Enable GPIO clock ****************************************/
  __HAL_RCC_GPIOA_CLK_ENABLE();
  /* Enable DMA2 clock */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ##########################################*/
  /* ADC Channel GPIO pin configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);

  /*##-3- Configure the DMA streams ##########################################*/
  /* Set the parameters to be configured */
  hdma_adc.Instance = DMA2_Stream0;
  hdma_adc.Init.Channel  = DMA_CHANNEL_0;
  hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_adc.Init.Mode = DMA_CIRCULAR;
  hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
  hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  hdma_adc.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
  hdma_adc.Init.MemBurst = DMA_MBURST_SINGLE;
  hdma_adc.Init.PeriphBurst = DMA_PBURST_SINGLE;

  HAL_DMA_Init(&hdma_adc);

  /* Associate the initialized DMA handle to the ADC handle */
  __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc);

  /*##-4- Configure the NVIC for DMA #########################################*/
  /* NVIC configuration for DMA transfer complete interrupt */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 8);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}

void DMA2_Stream0_IRQHandler(void)
{
  HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
}



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
Xcy
2019-07-20 08:31
后面屏蔽了其他外设功能及FreeRTOS测了一下,裸机跑功能是正常的。但是又出了一个奇怪的现象,在main函数里启动ADC后,在while循环里 计算各通道电压,只要调用uhADCxConvertedValue这个数组,DMA就出现问题,能进DMA中断,但是uhADCxConvertedValue数据不再更新。难道调用时需要暂停DMA? 我在STM32F1里都是直接调用计算的,没出现过这种情况。有人做过的,能否解答一下。

int main(void)
{
        u32 is_boot=0;
        u16 adc[3]={0};
       
        SCB->VTOR = FLASH_BASE | 0x20000;//设置偏移量

        Cache_Enable();                 //打开L1-Cache
        HAL_Init();                         //初始化HAL库
        Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz   
        bsp_Init();                     //板子外设初始化
   
        /* Infinite loop */
        while (1)
        {
                Model_Info.P_Power = uhADCxConvertedValue[1][0]*3300/4096;
                Model_Info.N_Power = uhADCxConvertedValue[1][1]*3300/4096;        
                HAL_Delay(10);
        }
}

一周热门 更多>