AnsweredAssumed Answered

STM32F334 ADC Scan DMA

Question asked by Manu Abraham on Apr 1, 2017
Latest reply on Apr 3, 2017 by KIC8462852 EPIC204278916

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);
}

Outcomes