AnsweredAssumed Answered

Timer triggered triple ADC regular sampling with DMA on STM32F7 - no interrupt

Question asked by eger.marcus on Jan 9, 2017
Latest reply on Jan 18, 2017 by eger.marcus

Hello all,

I have read through all contributions (e.g., STM32L ADC in Dual Regular Simultaneous Mode) and cubemx (1.5.0) examples I found but did not find a working solution. Timer triggered, single channel sampling via DMA works nicely (ADC1, but I checked also the other channels), see code extraction below. As soon as I comment (1) and uncomment (2) I do not get a DMA interrupt anymore.

What do I miss?
Thanks,
   Marcus

 

ADC_HandleTypeDef adcHdl1;
ADC_HandleTypeDef adcHdl2;
ADC_HandleTypeDef adcHdl3;

DMA_HandleTypeDef adcDmaHdl2_0;
DMA_HandleTypeDef adcDmaHdl2_1;
DMA_HandleTypeDef adcDmaHdl2_3;

 

static uint32_t adcData[6];    

 

int main(void) {
  ...
  MX_ADC_Init();
  /*(1)*/ HAL_ADC_Start_DMA(&adcHdl1, adcData, 2);   // DMA single channel ADC
  /*(2)*/ //HAL_ADCEx_MultiModeStart_DMA(&adcHdl1, (uint32_t *)adcData, 6); // DMA multimode (triple) ADC
  while(1);
}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *adcHdl) {
  ...
}


void MX_ADC_Init(void) {
  ADC_MultiModeTypeDef multimode;
  ADC_ChannelConfTypeDef sConfig;

 

  adcHdl1.Instance = ADC1;
  adcHdl2.Instance = ADC2;
  adcHdl3.Instance = ADC3;
    
  adcSetParameters(&adcHdl1);
  adcHdl1.Init.DMAContinuousRequests     = ENABLE;
  adcHdl1.Init.ExternalTrigConv          = ADC_EXTERNALTRIGCONV_T5_TRGO;    
  adcHdl1.Init.ExternalTrigConvEdge      = ADC_EXTERNALTRIGCONVEDGE_RISING;

 

  adcSetParameters(&adcHdl2);
  adcHdl2.Init.DMAContinuousRequests     = DISABLE;
  adcHdl2.Init.ExternalTrigConv          = ADC_EXTERNALTRIGCONV_T1_CC1;        
  adcHdl2.Init.ExternalTrigConvEdge      = ADC_EXTERNALTRIGCONVEDGE_NONE;    
    
  adcSetParameters(&adcHdl3);
  adcHdl3.Init.DMAContinuousRequests     = DISABLE;
  adcHdl3.Init.ExternalTrigConv          = ADC_EXTERNALTRIGCONV_T1_CC1;        
  adcHdl3.Init.ExternalTrigConvEdge      = ADC_EXTERNALTRIGCONVEDGE_NONE;    
    
  if (HAL_ADC_Init(&adcHdl1) != HAL_OK) Error_Handler(PANIC);
  if (HAL_ADC_Init(&adcHdl2) != HAL_OK) Error_Handler(PANIC);
  if (HAL_ADC_Init(&adcHdl3) != HAL_OK) Error_Handler(PANIC);
    
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

  sConfig.Channel = ADC_CHANNEL_3;
  if (HAL_ADC_ConfigChannel(&adcHdl1, &sConfig) != HAL_OK) Error_Handler(PANIC);

  sConfig.Channel = ADC_CHANNEL_6;
  if (HAL_ADC_ConfigChannel(&adcHdl2, &sConfig) != HAL_OK) Error_Handler(PANIC);

  sConfig.Channel = ADC_CHANNEL_4;
  if (HAL_ADC_ConfigChannel(&adcHdl3, &sConfig) != HAL_OK) Error_Handler(PANIC);

 

  /**Configure the ADC multi-mode */
  /* (2) */
  /*  multimode.Mode          = ADC_TRIPLEMODE_REGSIMULT;
  multimode.DMAAccessMode     = ADC_DMAACCESSMODE_1;
  multimode.TwoSamplingDelay  = ADC_TWOSAMPLINGDELAY_5CYCLES;
  HAL_ADCEx_MultiModeConfigChannel(&adcHdl1, &multimode);  */
}


void adcSetParameters(ADC_HandleTypeDef* adcHdl) {
  adcHdl->Init.ClockPrescaler           = ADC_CLOCKPRESCALER_PCLK_DIV4;
  adcHdl->Init.Resolution               = ADC_RESOLUTION12b;
  adcHdl->Init.ScanConvMode             = DISABLE;
  adcHdl->Init.ContinuousConvMode       = DISABLE;
  adcHdl->Init.DiscontinuousConvMode    = DISABLE;
  adcHdl->Init.DataAlign                = ADC_DATAALIGN_RIGHT;
  adcHdl->Init.NbrOfConversion          = 1;
  adcHdl->Init.EOCSelection             = ADC_EOC_SINGLE_CONV;
}
    
    
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHdl) {
  GPIO_InitTypeDef GPIO_InitStruct;
    __HAL_RCC_DMA2_CLK_ENABLE();

 

  if(adcHdl->Instance==ADC1) {
    __ADC1_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

    adcDmaHdl2_0.Instance                 = DMA2_Stream0;
    adcDmaHdl2_0.Init.Channel             = DMA_CHANNEL_0;
    adcDmaHdl2_0.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    adcDmaHdl2_0.Init.PeriphInc           = DMA_PINC_DISABLE;
    adcDmaHdl2_0.Init.MemInc              = DMA_MINC_ENABLE;
    adcDmaHdl2_0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    adcDmaHdl2_0.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
    adcDmaHdl2_0.Init.Mode                = DMA_CIRCULAR;
    adcDmaHdl2_0.Init.Priority            = DMA_PRIORITY_HIGH;
    adcDmaHdl2_0.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
    adcDmaHdl2_0.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
    adcDmaHdl2_0.Init.MemBurst            = DMA_MBURST_SINGLE;
    adcDmaHdl2_0.Init.PeriphBurst         = DMA_PBURST_SINGLE;

 

    HAL_DMA_Init(&adcDmaHdl2_0);
    __HAL_LINKDMA(adcHdl, DMA_Handle, adcDmaHdl2_0);

    HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
  }
  else if(adcHdl->Instance==ADC2)   {    ... }
  else if(adcHdl->Instance==ADC3)   { ... }

  HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);        
  HAL_NVIC_EnableIRQ(ADC_IRQn);
}

 

void DMA2_Stream0_IRQHandler(void) {
  HAL_DMA_IRQHandler(&adcDmaHdl2_0);
}

Outcomes