OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4003|回复: 3

请教STM32F767使用ADC采样的双缓冲DMA的方法

[复制链接]

1

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2020-7-27
在线时间
3 小时
发表于 2020-10-23 13:29:08 | 显示全部楼层 |阅读模式
1金钱
因为项目需要连续采样数据超过65536,可是ADC的单缓冲DMA的最大采样数量是65536个数据,因此想要采用双缓冲的方式,当数量大于65536个数量时切换buffer的地址,把后续的数据放到另外一个缓冲中,采用了下面的配置方法,可是启动不了另外一个缓冲,哪位大神帮看看,哪里不对




void bsp_Init_DBDMA(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    DMA_HandleTypeDef DMA_Handle = {0};
//   HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams = {0};



        __HAL_RCC_DMA2_CLK_ENABLE();   


        ADC1DMA_Handler.Instance=DMA2_Stream0;  
        ADC1DMA_Handler.Init.Channel=DMA_CHANNEL_0;
        ADC1DMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;
        ADC1DMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;
        ADC1DMA_Handler.Init.MemInc=DMA_MINC_ENABLE;
        ADC1DMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
        ADC1DMA_Handler.Init.MemDataAlignment=DMA_PDATAALIGN_HALFWORD;
        ADC1DMA_Handler.Init.Mode=DMA_CIRCULAR;
        ADC1DMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;
        ADC1DMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
        ADC1DMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
        ADC1DMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;
        ADC1DMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;
        ADC1DMA_Handler.XferCpltCallback = HAL_DMA_IRQHandler;
        HAL_DMA_DeInit(&ADC1DMA_Handler);   
        HAL_DMA_Init(&ADC1DMA_Handler);


    /* 开启DMA1 Stream1的中断 */
        __HAL_LINKDMA(&ADC1_Handler,DMA_Handle,ADC1DMA_Handler);
        __HAL_DMA_ENABLE_IT(&ADC1DMA_Handler,DMA_IT_TC) ;  
        HAL_NVIC_SetPriority(DMA2_Stream0_IRQn,0,0);
        HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

    ADC1_Handler.Instance = ADC1;
    ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
    ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式
    ADC1_Handler.Init.ScanConvMode = ENABLE;                    //非扫描模式
    ADC1_Handler.Init.ContinuousConvMode = ENABLE;              //关闭连续转换
    ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式
    ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
    ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发
    ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐
    ADC1_Handler.Init.NbrOfConversion = 1;                       //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DMAContinuousRequests = ENABLE;           //关闭DMA请求
    ADC1_Handler.Init.EOCSelection = ADC_EOC_SINGLE_CONV;        
    HAL_ADC_Init(&ADC1_Handler);   

    ADC1_ChanConf.Channel = ADC_CHANNEL_11;  //AE                          
        ADC1_ChanConf.Rank = 1;                                    
        ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_15CYCLES;//ADC_SAMPLETIME_3CYCLES;
        ADC1_ChanConf.Offset = 0;
        HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);


   //  启动DMA双缓冲传输

    HAL_ADC_MspInit(&ADC1_Handler);
    HAL_DMAEx_MultiBufferStart(&ADC1DMA_Handler, (uint32_t )ADC1, (uint32_t )&buffer1[0],(uint32_t )&buffer2[0], 50000);
       
     // HAL_DMAEx_MultiBufferStart_IT(&ADC1DMA_Handler, (uint32_t )ADC1, (uint32_t )&buffer1[0],(uint32_t )&buffer2[0], 50000);
    //   HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer1, AE_SAMPLE_POINT);


}



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2020-7-27
在线时间
3 小时
 楼主| 发表于 2020-10-23 15:48:50 | 显示全部楼层
这个方法实现了,其实也挺简单
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2020-7-27
在线时间
3 小时
 楼主| 发表于 2020-10-23 16:23:51 | 显示全部楼层
HAL_ADC_Start_DDMA(&ADC1_Handler, (uint32_t *)buffer1, (uint32_t *)buffer2, 65535);

HAL_StatusTypeDef HAL_ADC_Start_DDMA(ADC_HandleTypeDef* hadc, uint32_t* pData,uint32_t* pData1, uint32_t Length)
{
  __IO uint32_t counter = 0;
  
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
  assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge));
  
  /* Process locked */
  __HAL_LOCK(hadc);
  
  /* Enable the ADC peripheral */
  /* Check if ADC peripheral is disabled in order to enable it and wait during
     Tstab time the ADC's stabilization */
  if((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON)
  {  
    /* Enable the Peripheral */
    __HAL_ADC_ENABLE(hadc);
   
    /* Delay for ADC stabilization time */
    /* Compute number of CPU cycles to wait for */
    counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000));
    while(counter != 0)
    {
      counter--;
    }
  }
  
  /* Start conversion if ADC is effectively enabled */
  if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON))
  {
    /* Set ADC state                                                          */
    /* - Clear state bitfield related to regular group conversion results     */
    /* - Set state bitfield related to regular group operation                */
    ADC_STATE_CLR_SET(hadc->State,
                      HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR,
                      HAL_ADC_STATE_REG_BUSY);
   
    /* If conversions on group regular are also triggering group injected,    */
    /* update ADC state.                                                      */
    if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
    {
      ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);  
    }
   
    /* State machine update: Check if an injected conversion is ongoing */
    if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
    {
      /* Reset ADC error code fields related to conversions on group regular */
      CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));         
    }
    else
    {
      /* Reset ADC all error code fields */
      ADC_CLEAR_ERRORCODE(hadc);
    }
   
    /* Process unlocked */
    /* Unlock before starting ADC conversions: in case of potential           */
    /* interruption, to let the process to ADC IRQ Handler.                   */
    __HAL_UNLOCK(hadc);   

    /* Set the DMA transfer complete callback */
    hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;

    /* Set the DMA half transfer complete callback */
    hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
   
    /* Set the DMA error callback */
    hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;

   
    /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC     */
    /* start (in case of SW start):                                           */
   
    /* Clear regular group conversion flag and overrun flag */
    /* (To ensure of no unknown state from potential previous ADC operations) */
    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC | ADC_FLAG_OVR);

    /* Enable ADC overrun interrupt */
    __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR);
   
    /* Enable ADC DMA mode */
    hadc->Instance->CR2 |= ADC_CR2_DMA;
   
    /* Start the DMA channel */
  //  HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
    HAL_DMAEx_MultiBufferStart_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData,(uint32_t)pData1, Length);   
    /* Check if Multimode enabled */
    if(HAL_IS_BIT_CLR(ADC->CCR, ADC_CCR_MULTI))
    {
      /* if no external trigger present enable software conversion of regular channels */
      if((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)
      {
        /* Enable the selected ADC software conversion for regular group */
        hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
      }
    }
    else
    {
      /* if instance of handle correspond to ADC1 and  no external trigger present enable software conversion of regular channels */
      if((hadc->Instance == ADC1) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET))
      {
        /* Enable the selected ADC software conversion for regular group */
          hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
      }
    }
  }
  
  /* Return function status */
  return HAL_OK;
}
回复

使用道具 举报

4

主题

84

帖子

1

精华

高级会员

Rank: 4

积分
666
金钱
666
注册时间
2013-10-21
在线时间
88 小时
发表于 2020-12-6 12:11:49 | 显示全部楼层
qxdclx 发表于 2020-10-23 16:23
HAL_ADC_Start_DDMA(&ADC1_Handler, (uint32_t *)buffer1, (uint32_t *)buffer2, 65535);

HAL_StatusTyp ...

你自己写了个函数实现了?HAL库自带的函数不行吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-13 17:48

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表