cancel
Showing results for 
Search instead for 
Did you mean: 

DMA only fetching 2 values from ADC

John Hite
Associate III
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.

}
8 REPLIES 8
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 Venmo
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
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
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

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...

Posted on April 21, 2017 at 18:59

Could you expand on 'No interrupt, full HW...' a bit?

 I am trying to figure out why the DMA is shutting down my ADC.

Thanks,

JH

Posted on April 21, 2017 at 23:40

DMA in the background, happens behind back of CPU and debugger

&sharpdefine ADC_NUM_READINGS 8 // Changing these will require a significant change

void adcInit(void);

uint16_t readVoltage(void);

volatile uint16_t adc2_result[ADC_NUM_READINGS];

static DMA_InitTypeDef dma2 =

{

DMA_Channel_1,

(uint32_t)&ADC2->DR, // ADC2->DR

(uint32_t)&adc2_result[0], // Memory 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 GPIO_Configure(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void adcInit(void)

{

ADC_CommonInitTypeDef cInit;

ADC_InitTypeDef init = { 0 }; // Or initialize ALL fields

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_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

init.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

init.ADC_DataAlign = ADC_DataAlign_Right;

init.ADC_NbrOfConversion = 1;

ADC_Init(ADC2, &init);

ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 1, ADC_SampleTime_15Cycles);

ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); // Recycles after DMA completes

ADC_DMACmd(ADC2, ENABLE);

ADC_Cmd(ADC2, ENABLE);

ADC_SoftwareStartConv(ADC2); // Start first time

}

uint16_t readVoltage(void)

{

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

}

/**

* @brief Main program

* @param None

* @retval None

*/

int main(void)

{

/*!< At this stage the microcontroller clock setting is already configured,

this is done through SystemInit() function which is called from startup

file (startup_stm32f4xx.s) before to branch to application main.

To reconfigure the default setting of SystemInit() function, refer to

system_stm32f4xx.c file

*/

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

GPIO_Configure();

memset((void *)adc2_result, 0xCD, sizeof(adc2_result));

adcInit();

while(1)

{

static int i = 0;

i += readVoltage();

}

while (1)

{

}

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 23, 2017 at 11:03

 I am trying to figure out why the DMA is shutting down my ADC.

And does it? How do you know? Post the content of relevant ADC and DMA registers.

JW

Posted on April 23, 2017 at 16:02

There are problem with the ADC initialization due to several missing fields containing junk values. The ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); is needed to sustain the stream.

Keil also threw warnings about the addresses in the constant structure, but the linker seemed to fix up properly.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..