Skip to main content
John Hite
Associate III
April 20, 2017
Question

DMA only fetching 2 values from ADC

  • April 20, 2017
  • 2 replies
  • 1043 views
Posted on April 20, 2017 at 18:01

STM32F437

This is an update from my previous thread:

https://community.st.com/message/154808-stm32f4-adcdma-always-returns-same-value

 

The ADC2 DR has the right value in it but the DMA is not working as I thought it would. It is only transferring 2 values although the array size and # of readings is 8. Condensed code is below.

Thanks,

JH

#define ADC_NUM_READINGS 8  //  Changing these will require a significant change

void AdcInit(void);

uint16_t readVoltage(void);

static uint16_t adc2_result[ADC_NUM_READINGS];

static const DMA_InitTypeDef dma2 =

{

    DMA_Channel_1,

    ADC2_BASE + 0x4C,                       //  ADC2->DR

    (uint32_t)&adc2_result,               //Mememory 0 base address

    DMA_DIR_PeripheralToMemory,

    ADC_NUM_READINGS,

    DMA_PeripheralInc_Disable,

    DMA_MemoryInc_Enable,

    DMA_PeripheralDataSize_HalfWord,

    DMA_MemoryDataSize_HalfWord,

    DMA_Mode_Circular,

    DMA_Priority_High,

    DMA_FIFOMode_Disable,

    DMA_FIFOThreshold_Full,

    DMA_MemoryBurst_Single,

    DMA_PeripheralBurst_Single

};

void adcInit(void)

{

    ADC_CommonInitTypeDef cInit;

    ADC_InitTypeDef init;

    OS_ERR err;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

    DMA_DeInit(DMA2_Stream2);

    DMA_Init(DMA2_Stream2, (DMA_InitTypeDef*)&dma2);

    DMA_Cmd(DMA2_Stream2, ENABLE);

    cInit.ADC_Mode = ADC_Mode_Independent;

    cInit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

    cInit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

    cInit.ADC_Prescaler = ADC_Prescaler_Div2;

    ADC_CommonInit(&cInit);

    init.ADC_Resolution = ADC_Resolution_12b;

    init.ADC_ScanConvMode = DISABLE;

    init.ADC_ContinuousConvMode = ENABLE;

    init.ADC_DataAlign = ADC_DataAlign_Right;

    init.ADC_NbrOfConversion = 1;

    ADC_Init(ADC2, &init);

    ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 1, ADC_SampleTime_15Cycles);

    //ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);

    ADC_DMACmd(ADC2, ENABLE);

    ADC_Cmd(ADC2, ENABLE);

    ADC_SoftwareStartConv(ADC2);

}

uint16_t readVoltage(void)

{

   return adc2_result[0];   // I set a break point here and examine the array. Locations 2-7 are always zero.

}
    This topic has been closed for replies.

    2 replies

    Tesla DeLorean
    Guru
    April 20, 2017
    Posted on April 20, 2017 at 18:56

    ADC_InitTypeDef init = { 0 }; // try doing this

    Also

    ADC2_BASE + 0x4C,                       //  ADC2->DR

    Wouldn't (uint32_t)&ADC2->DR be simpler/clearer?

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    S.Ma
    Principal
    April 20, 2017
    Posted on April 20, 2017 at 21:11

    The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6rz&d=%2Fa%2F0X0000000bwy%2FmHDLRRpZscAToHdpPUWEEb2pUH3oSHKoFDNQQfdVvFY&asPdf=false
    John Hite
    John HiteAuthor
    Associate III
    April 21, 2017
    Posted on April 21, 2017 at 16:39

    Thanks for the post Clive. I walked through your code and the only difference I see is in the buffer size and that you define external trigger configurations. But since I am using continuous ADC triggering that shouldn't matter.

    The fact remains that if I enable DMA the ADC never updates its data register after the first reading. Also I still only get one or two values from the DMA for that first transfer. I am beginning to wonder if the DMA does not work without an ISR manipulating its registers.

    JH

    S.Ma
    Principal
    April 21, 2017
    Posted on April 21, 2017 at 18:33

    Actually with the external trigger, the ADC buffer fills up even if the code is stopped by breakpoint. No interrupt, full HW...