AnsweredAssumed Answered

STM32F4 ADC Triple Mode DMA Interrupt problem

Question asked by pantelis on Jun 24, 2015
Latest reply on Jun 28, 2015 by pantelis
Hi everyone!

I hope it is not a problem opening two threads with similar subject consequtively (but actually different :D ). I have the written the following code to use ADC Triple mode and consequtive data transfer using DMA, but the DMA interrupt is never entered. I also tried to change the flag to the error interrupt, but not even this is entered by the code.

Could you please have a look and tell me what might be the issue?

The code is :
Header File

#ifndef ADC_DMA_H_
#define ADC_DMA_H_

#include "stm32f4xx_conf.h"

ADC_InitTypeDef       ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef       DMA_InitStructure;
GPIO_InitTypeDef      GPIO_InitStructure;
NVIC_InitTypeDef       NVIC_InitStructure2;

typedef struct {

    volatile uint32_t A;
    volatile uint32_t B;
    volatile uint32_t C;
} ADCinputs;

extern ADCinputs AnlgInput;

extern volatile uint32_t Measuredvalues[3];

void ADC_Config(void);
void DMA_Config(void);

void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream2_IRQHandler(void);
void DMA2_Stream1_IRQHandler(void);

void LED_Config(void); // Test function created in order to test the DMA Transfer Times

#endif /* ADC_DMA_H_ */

Source File

 * ADC_DMA.c
 *  Created on: 23.06.2015
 *      Author: ppapaman

#include "ADC_DMA.h"
ADCinputs AnlgInput;

int test=0;

volatile uint32_t Measuredvalues[3];

void ADC_Config(void)

  /* Enable ADC1, ADC2, ADC3 and GPIO clocks */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

  /* Configure ADC1 Channel10, ADC2 Channel 11 and ADC3 Channel 12 pins as analog inputs (Correspond to PC0, PC1 and PC2)*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init (ADC_CCR register) */
  ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; // ADC_Mode_Independent for 1 ADC. For ADC123, it will change to ADC_TripleMode_RegSimult!
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; //ADC_DMAAccessMode_1; Enable it in mode 2 or 3 with multi input
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  /* ADC1 Init (ADC_CR1 & ADC_CR2 registers)*/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE; // Each ADC Scans one channel so I think that even in triple mode it won't be used
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1; // One signal scanning
  ADC_Init(ADC1, &ADC_InitStructure);
  ADC_Init(ADC2, &ADC_InitStructure);
  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC1 regular channel10 configuration*/
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 1, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_3Cycles);

  /* Enable ADC1 */


void DMA_Config(void)
      // Enable DMA clocks
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

      // DMA2 Stream0 channe0 configuration for ADC1
      DMA_InitStructure.DMA_Channel = DMA_Channel_0;  // Represents the channel of DMA2 Used by ADC1(RM0090 Table 43)
      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // Address of ADC Common Data register &ADC1->DR; &ADC->CDR; RM0090 Table.72
      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&AnlgInput.A; //Measuredvalues or AnlgInput.A
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
      DMA_InitStructure.DMA_BufferSize = 2;
      DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
      DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
      DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
      DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
      DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
      DMA_InitStructure.DMA_Priority = DMA_Priority_High;
      DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
      DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
      DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
      DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
      DMA_Init(DMA2_Stream0, &DMA_InitStructure);
      DMA_Cmd(DMA2_Stream0, ENABLE);

      // DMA2 Stream2 channe1 configuration for ADC2
      DMA_InitStructure.DMA_Channel = DMA_Channel_1;
      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR; // Address of ADC2 Data register RM0090 Table.72
      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&AnlgInput.B;
      DMA_Init(DMA2_Stream2, &DMA_InitStructure);
      DMA_Cmd(DMA2_Stream2, ENABLE);

      // DMA2 Stream1 channe2 configuration for ADC3
      DMA_InitStructure.DMA_Channel = DMA_Channel_2;
      DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC3->DR; // Address of ADC3 Data register RM0090 Table.72
      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&AnlgInput.C;
      DMA_Init(DMA2_Stream1, &DMA_InitStructure);
      DMA_Cmd(DMA2_Stream1, ENABLE);

      /* Enable DMA request after last transfer (Multi-ADC mode)  */

      // Enable DMA request after last transfer (Single-ADC mode)
        ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
        ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
        ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

      // Enable ADC1 DMA since it is the master

      // Start ADC1 Software Conversions


      //Once transfer of ADC1 is done, generate interrupt
      NVIC_InitStructure2.NVIC_IRQChannel = DMA2_Stream0_IRQn;
      NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 0;
      NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 0;
      NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;

      //Once transfer of ADC2 is done, generate interrupt
      NVIC_InitStructure2.NVIC_IRQChannel = DMA2_Stream2_IRQn;

      //Once transfer of ADC3 is done, generate interrupt
      NVIC_InitStructure2.NVIC_IRQChannel = DMA2_Stream1_IRQn;


void DMA2_Stream0_IRQHandler(void)

    if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0)!=RESET)

        if (test%2==1)
            GPIOC->BSRRH = GPIO_Pin_13;
            GPIOC->BSRRL = GPIO_Pin_13;

        if (test>=100) test=0;

        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);


void DMA2_Stream2_IRQHandler(void)


void DMA2_Stream1_IRQHandler(void)


void LED_Config(void)

    GPIO_InitTypeDef GPIO_InitStructure;

    // Enable clock
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

    // Configure GPIO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

Thank you in advance!