cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F334 ADC Scan DMA

Manu Abraham
Senior
Posted on April 01, 2017 at 20:22

Hi,

Trying to do a ADC continuous scan with 4 sequential channels using DMA, ending up with one single DMA Transfer Complete Interrupt, though I am clearing the TC interrupt. The single transfer has the correct ADC result for all the 4 channels, but it fires just once alone. Read the Reference manual a few times, but cant find what I am indeed missing to get the Continuous Conversion working. Aargh! Obviously, I am missing something ..  Is someone kind enough to lend a set of eyeballs, to find what I am missing ?

Thanks!

The output what I get:

DMA1_TC

::0 1653 0 1

extern char adcstr[50];

uint16_t ADCVal[4] = {0, 0, 0, 0};

void DMA1_Channel1_IRQHandler(void)

{

    if (DMA_GetITStatus(DMA1_IT_TC1)) {

        putstr(USART1, 'DMA1_TC\r');

        sprintf((char*)adcstr, '::%d %d %d %d\r', ADCVal[0], ADCVal[1], ADCVal[2], ADCVal[3]);

        putstr(USART1, adcstr);

        DMA_ClearITPendingBit(DMA1_IT_TC1);

    }

    if (DMA_GetITStatus(DMA1_IT_TE1)) {

        putstr(USART1, 'DMA1_TE\r');

        DMA_ClearITPendingBit(DMA1_IT_TE1);

    }

}

void adc_dmascan_init(void)

{

    __IO uint32_t        cal_factor = 0;

    ADC_InitTypeDef        adci;

    ADC_CommonInitTypeDef    adcc;

    DMA_InitTypeDef        dma;

    /* ADC and GPIO clk config */

    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);        /* ADC12 clock = PLLCLK/2 */

    __ADC12_CLK_ENABLE();                /* enable ADC1 clock */

    __ADC_VREG_ENABLE(ADC1);            /* enable ADC voltage regulator */

    delay(10);                    /* wait 10uS */

    __ADC_CALMODE_SINGLE(ADC1);            /* calibrate single ended */

    __ADC_CALIBRATE(ADC1);

    while (!__ADC_CAL_DONE(ADC1));

    cal_factor = __ADC_CAL_FACTOR(ADC1);

    /* setup DMA Ch:1    */

    __DMA1_CLK_ENABLE();

    dma.DMA_DIR            = DMA_DIR_PeripheralSRC;

    dma.DMA_Mode            = DMA_Mode_Circular;

    dma.DMA_PeripheralBaseAddr    = (uint32_t)&ADC1->DR;

    dma.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_HalfWord;

    dma.DMA_PeripheralInc        = DMA_PeripheralInc_Disable;

    dma.DMA_MemoryBaseAddr        = (uint32_t)&ADCVal;

    dma.DMA_BufferSize        = 4;

    dma.DMA_MemoryDataSize        = DMA_MemoryDataSize_HalfWord;

    dma.DMA_MemoryInc        = DMA_MemoryInc_Enable;

    dma.DMA_Mode            = DMA_Mode_Normal;

    DMA_Init(DMA1_Channel1, &dma);

    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);

    DMA_ITConfig(DMA1_Channel1, DMA_IT_TE, ENABLE);

    NVIC_EnableIRQ(DMA1_Channel1_IRQn);

    /* ADC Common Init    */

    adcc.ADC_Mode            = ADC_Mode_Independent;

    adcc.ADC_DMAAccessMode        = ADC_DMAAccessMode_Disabled;

    adcc.ADC_DMAMode        = ADC_DMAMode_Circular;

    adcc.ADC_Clock            = ADC_Clock_AsynClkMode;

    adcc.ADC_TwoSamplingDelay    = 0;

    ADC_CommonInit(ADC1, &adcc);

    /* ADC Init    */

    ADC_StructInit(&adci);

    adci.ADC_Resolution        = ADC_Resolution_12b;

    adci.ADC_ContinuousConvMode    = ADC_ContinuousConvMode_Enable;

    adci.ADC_DataAlign        = ADC_DataAlign_Right;

    adci.ADC_NbrOfRegChannel    = 4;

    adci.ADC_ExternalTrigConvEvent    = ADC_ExternalTrigConvEvent_0;

    adci.ADC_ExternalTrigEventEdge    = ADC_ExternalTrigEventEdge_None;

    adci.ADC_OverrunMode        = ADC_OverrunMode_Disable;

    adci.ADC_AutoInjMode        = ADC_AutoInjec_Disable;

    ADC_Init(ADC1, &adci);

    /* Select channels to read    */

    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_181Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_181Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_181Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_181Cycles5);

    ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);

    ADC_DMACmd(ADC1, ENABLE);

    ADC_Cmd(ADC1, ENABLE);

    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));

    DMA_Cmd(DMA1_Channel1, ENABLE);

    ADC_StartConversion(ADC1);

}
2 REPLIES 2
Manu Abraham
Senior
Posted on April 01, 2017 at 20:32

Gah, After posting alone,  noticed the weird issue, that I overwrote the DMA_Mode ..

    dma.DMA_Mode            = DMA_Mode_Circular;

That fixed it and it works as expected ..

DMA1_TC

::0 1700 3 0

DMA1_TC

::0 1684 0 0

DMA1_TC

::0 1734 0 0

Sorry about the noise.

Posted on April 03, 2017 at 11:48

It will be useful for people exploring the forum for solutions. This will surely help others.