AnsweredAssumed Answered

Unable to get EOC on Triple ADC mode

Question asked by thompson.rob on Apr 21, 2016
Latest reply on Apr 21, 2016 by thompson.rob
I'm trying to get ADC Scan Conversion (Single Scan, regular channel conversion) to work on an STM32F405VG using Triple ADC mode and DMA but I am not seeing End of Conversion. Any ideas?

static const uint8_t adc1RegularChannelSeq[] =
{
    ADC_Channel_15,
    ADC_Channel_3
};
static const uint8_t adc2RegularChannelSeq[] =
{
    ADC_Channel_1,
    ADC_Channel_11
};
static const uint8_t adc3RegularChannelSeq[] =
{
    ADC_Channel_2,
    ADC_Channel_12
};

volatile uint16_t adcConvertedValues[6];

void CpuAdcGpioConfig (void)
{
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2, ENABLE )

    // Enable ADC related GPIO clocks
    RCC_AHB1PeriphClockCmd( GPIOA | GPIOC, ENABLE );

    // Setup common Analog input pin characteristics
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit( &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    // Apply characteristics to each pin
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init( GPIOC, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init( GPIOC, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init( GPIOC, &GPIO_InitStructure );
}

void CpuAdcDmaConfig (void)
{
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2, ENABLE );

    // DMA Stream Configuration
    DMA_InitTypeDef DMA_InitStructure;
    DMA_StructInit( &DMA_InitStructure );
    DMA_InitStructure.DMA_Channel            = ADC_DMA_CHANNEL;
    DMA_InitStructure.DMA_Memory0BaseAddr    = (uint32_t)adcConvertedValues;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(ADC->CDR);
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize         = 6;
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
    DMA_Init( ADC_DMA_STREAM, &DMA_InitStructure );

    // ADC related DMA stream enable
    DMA_Cmd( DMA2_Stream0, ENABLE );
}

void CpuAdcPeriphConfig (void)
{
    RCC_APB2PeriphClockCmd( ( RCC_APB2Periph_ADC1 |
                              RCC_APB2Periph_ADC2 |
                              RCC_APB2Periph_ADC3 ), ENABLE );

    ADC_CommonStructInit(&ADC_CommonInitStructure);
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_CommonInitStructure.ADC_Mode             = ADC_TripleMode_RegSimult;
    ADC_CommonInitStructure.ADC_Prescaler        = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_1;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    // Configure individual ADC parameters.
    ADC_InitTypeDef ADC_InitStructure;
    ADC_StructInit( &ADC_InitStructure );
    ADC_InitStructure.ADC_Resolution           = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode         = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode   = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign            = ADC_DataAlign_Right;
    
    ADC_InitStructure.ADC_NbrOfConversion = 2;
    ADC_Init(ADC1, &ADC_InitStructure);
    ADC_InitStructure.ADC_NbrOfConversion = 2;
    ADC_Init(ADC2, &ADC_InitStructure);
    ADC_InitStructure.ADC_NbrOfConversion = 2;
    ADC_Init(ADC3, &ADC_InitStructure);

    // Set ADC regular channel sequence
    uint16_t i;
    for ( i = 0; i < 2; i++ )
    {
        ADC_RegularChannelConfig( ADC1, adc1RegularChannelSeq[i], (i + 1), ADC_SampleTime_3Cycles );
    }
    for ( i = 0; i < 2; i++ )
    {
        ADC_RegularChannelConfig( ADC2, adc2RegularChannelSeq[i], (i + 1), ADC_SampleTime_3Cycles );
    }
    for ( i = 0; i < 2; i++ )
    {
        ADC_RegularChannelConfig( ADC3, adc3RegularChannelSeq[i], (i + 1), ADC_SampleTime_3Cycles );
    }

    // Enable DMA request after last transfer (Multi-ADC mode)
    ADC_MultiModeDMARequestAfterLastTransferCmd( ENABLE);

    // Enable all needed ADCs.
    ADC_Cmd(ADC1, ENABLE);
    ADC_Cmd(ADC2, ENABLE);
    ADC_Cmd(ADC3, ENABLE);

    // Enable DMA requests
    ADC_DMACmd(ADC1, ENABLE);
    ADC_DMACmd(ADC2, ENABLE);
    ADC_DMACmd(ADC3, ENABLE);
}

void CpuAdcTest (void)
{
    FlagStatus endOfConv;
    uint16_t copyAdcConvertedValues[6];

    // Initialize ADC
    CpuAdcGpioConfig();
    CpuAdcDmaConfig();
    CpuAdcPeriphConfig();

    // Start ADC Software Conversion
    ADC_SoftwareStartConv(ADC1);

    // Each A/D's end of conversion should be set at end of sequence.
    // Test them to show A/D conversions were done.
    do
    {
        endOfConv = ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC );
    } while ( ! endOfConv );

    // ---NEVER GETS HERE---- (also, never see OVR flag)

    do
    {
        endOfConv = ADC_GetFlagStatus( ADC2, ADC_FLAG_EOC );
    } while ( ! endOfConv );

    do
    {
        endOfConv = ADC_GetFlagStatus( ADC3, ADC_FLAG_EOC );
    } while ( ! endOfConv );

    // Wait for End of Scan conversion & DMA transfer complete
    do
    {
        ;
    } while ( SET != DMA_GetFlagStatus( ADC_DMA_STREAM, ADC_DMA_FLAG_TCIF ) );

    // Keep a copy of converted values to inspect.
    for ( i = 0; i < 6; i++ )
    {
        copyAdcConvertedValues[i] = adcConvertedValues[i];
    }
    
}

Outcomes