AnsweredAssumed Answered

STM32F407 Discovery w/ 3 Channel ADC and DMA

Question asked by luzuriaga.nichol.007 on Jan 21, 2015
Latest reply on Jan 22, 2015 by AvaTar
Looking through this forum I have seen the topic of ADCs and DMAs coming up a lot, and I apologize in advance for adding to it. but after reviewing most posts I still have not been able to implement ADC with the DMA.

When trying to read from the memory locations I get a return value of 0, which has me believe that the DMA is not working because values are not being transferred. Moreover, when I just read straight from the ADC1->DR register, I will only ever get a constant value for each runtime which varies between 200-300. Thank you in advance.

#include "stm32f4.h"
 
volatile uint16 adcVal[3];
 
extern void initialise_monitor_handles(void); /* prototype */
void ADC_DMA_Init(void)
{
 
    RCC->AHB1ENR                |= (1<<22);             /* DMA2 clk Enable*/
    DMA2->stream[0].CR          &= ~(0x0E000000);           /* Channel 0 selected */
    DMA2->stream[0].CR          &= ~(0x01800000);           /* Memory bust single*/
    DMA2->stream[0].CR          &= ~(0x00600000);           /* Peripheral bust single*/
    DMA2->stream[0].CR          |= (2<<16)|             /* Priority level High */
                                   (1<<13)|         /* Memory data size Half-word*/
                                   (1<<11)|         /* Peripheral data size Half-word*/
                                   (1<<10)|         /* Memory increment  enable */
                                   (0<<9)|              /* Peripheral increment disable*/
                                   (1<<8);              /* Circular mode enable*/
 
    DMA2->stream[0].CR          &= ~(0x000000C0);           /* Direction Peripheral to Memory*/
    DMA2->stream[0].NDTR        = 3;                    /* Number of data items*/
    DMA2->stream[0].PAR         = (uint32) &ADC1->DR;       /* Peripheral base address*/
    DMA2->stream[0].M0AR        = (uint32) &adcVal[0];  /* Memory 0 base address*/
 
    DMA2->stream[0].FCR         = 0x00000021;               /* Direct mode and Threshold_HalfFull(Threshold not used) : same as reset value */
 
    DMA2->stream[0].CR          |= (1<<0);              /* DMA2_Stream0 Enable*/
 
 
 
    RCC->APB2ENR                |= (1<<8);              /* ADC1 clk enable*/
 
    GPIOA->MODER                |= (3<<(12));           /* PA6 - Channel6  */
    GPIOA->PUPDR                &= ~((3<<(12)));        /* No Pull up and down resistor*/
    GPIOC->MODER                |= ( 3<<(4)) | (3<<(8) );   /* PC2, PC4 - Channel 12,14 */
    GPIOC->PUPDR                &= ~( (3<<(4)) | (3<<(8)) );    /* No Pull up and down resistor*/
 
 
    ADC1->CR1                   = (1<<8);                       /* Scan mode enable in order to read multi channel with single ADC*/
 
    ADC1->CR2                   = (1<<0)|                       /* ADC1 power on */
                                  (1<<1)|                       /* Continuous conversion*/
                                  (1<<8)|                       /* DMA access mode enable*/
                                  (1<<9);                       /* Enable the selected ADC DMA request after last transfer */
 
    ADC1->SMPR1                 = 0;
    ADC1->SMPR2                 = 0;                            /* PA3, PA5 3cycle*/
 
    ADC1->SQR1                  = (2<<20);                      /* three conversions */
    ADC1->SQR2                  = 0;
 
 
    ADC1->SQR3                  = (12<<0) | (6<<5) | (14<<10);      /* 1st: ADC1_IN12, 2nd: ADC1_IN6, 3rd: ADC1_IN14*/
    ADCCOMMON->CCR              = (1<<16);                    /* fpclk2/4 = 21Mhz */
 
 
    ADC1->CR2                   |= (1<<30);
}
 
int main (void) {
    initialise_monitor_handles();
 
    ADC_DMA_Init();
 
    ADC1->CR2 |= (1<<30);
 
    while (1)
    {
        // printf("%i\n", ADC1->DR);
        printf("{%i, %i, %i}\n", adcVal[0], adcVal[1], adcVal[2]);
    }
 
    return 0;
 
}

inside my stm32f4.h file I have the following defined:
#define DMA2                ((struct DMA_struct *)          0x40026400)
 
/* ... */
 
/* DMA - DMA Controller */
struct DMA_struct {
    volatile uint32     LISR;       /* Low Interrupt Status register                    */
    volatile uint32     HISR;       /* High Interrupt Status register                   */
    volatile uint32     LIFCR;      /* Low Interrupt Flag Clear register                */
    volatile uint32     HIFCR;      /* High Interrupt Flag Clear register               */
 
    struct DMAstream_struct stream[8];  /* DMA stream registers */
};
 
/* ... */
 
/* DMA stream structure, 8 streams per DMA */
struct DMAstream_struct {
    volatile uint32     CR;         /* Configuration register                           */
    volatile uint32     NDTR;       /* Number of data register                          */
    volatile uint32     PAR;        /* Peripheral Address register                      */
    volatile uint32     M0AR;       /* Memory Address 0 register                        */
    volatile uint32     M1AR;       /* Memory Address 1 register                        */
    volatile uint32     FCR;        /* Fifo Control register                            */
};

Outcomes