Skip to main content
Tapankaew.Sarod
Associate
November 26, 2013
Question

STM32F407 ADC+DMA PROBLEMS

  • November 26, 2013
  • 6 replies
  • 1164 views
Posted on November 26, 2013 at 16:31

I try to use adc_triplemode_regsimult to convert two phase ac voltage 50 Hz and current with

adc_DMAaccessmode_1 but DMA keep sending me wrong alignment in ADCConvertedValue[3].I noticed that DMA star to mess up when DMA_S0NDTR change from 3 to 2 or 1.Plese someone help me.Every answer would be appreciated.

Here is my code.

    This topic has been closed for replies.

    6 replies

    Tesla DeLorean
    Guru
    November 26, 2013
    Posted on November 26, 2013 at 16:45

    Not seeing any code, but is [3] valid? Wouldn't you get values in [0],[1],[2]?

    Some of these multiple modes are hard to set up and get your head around. Especially with 16-bit, 32-bit values, and arrays. Your buffer may need to accommodate multiple samples.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tapankaew.Sarod
    Associate
    November 26, 2013
    Posted on November 26, 2013 at 16:49

    #include ''stm32f4_discovery.h''

    #include ''rcc.h''

    #include ''ADC.h''

    #include ''DMA.h''

    int main(void)

    {  

        //RCC Configuration

        RCC_Config();

        //GPIO Configuration

        GPIO_Config();

        //DMA Configuration

        DMA_Config();    

        //ADC Configuration

        ADC_Config();

        while (1)

        { }

     }

    /****************************************************/

     void RCC_Config(void)

     {

     /* TIM3 clock enable */

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

      /* GPIOA GPIOB GPIOC GPIOD and GPIOE clock enable */

      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |RCC_AHB1Periph_GPIOB |    RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE , ENABLE);

     

     /* Enable ADC1 clocks ****************************************/

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);

        /* Enable ADC2 clocks ****************************************/

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2 , ENABLE);    

        /* Enable ADC3 clocks ****************************************/

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3 , ENABLE);    

      /* Enable DMA2 clocks ****************************************/

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,  ENABLE);

    }

    /****************************************************/

     void GPIO_Config(void)

      {

        GPIO_InitTypeDef GPIO_InitStructure;

     

      /* Configure ADC1 Channel0 pin as analog input */

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;

      GPIO_Init(GPIOA, &GPIO_InitStructure);

        

       /* Configure ADC2 Channel15 pin as analog input */

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;

      GPIO_Init(GPIOC, &GPIO_InitStructure);

        

      /* Configure ADC3 Channel10 pin as analog input */

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;

      GPIO_Init(GPIOC, &GPIO_InitStructure);

    }    

    /****************************************************/

    #define CDR_ADDRESS ((uint32_t)0x40012308)

    __IO uint16_t  ADCConvertedValue[3];

    void DMA_Config(void)

    {

        DMA_InitTypeDef       DMA_InitStructure;

        

        DMA_InitStructure.DMA_Channel = DMA_Channel_0;

        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)CDR_ADDRESS;

        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & ADCConvertedValue;

        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

        DMA_InitStructure.DMA_BufferSize = 3;

        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_PeripheralBurst_Single;

        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

        DMA_Init(DMA2_Stream0, &DMA_InitStructure);

        

        DMA_Cmd(DMA2_Stream0,ENABLE);

    }

    /****************************************************/

    void ADC_Config(void)

    {

      ADC_InitTypeDef       ADC_InitStructure;

      ADC_CommonInitTypeDef ADC_CommonInitStructure;

        

         /* ADC Common Init **********************************************************/

        ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;

        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1 ;  

        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

        ADC_CommonInit(&ADC_CommonInitStructure);

      /* ADC1 Init ****************************************************************/

        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

        ADC_InitStructure.ADC_ScanConvMode = DISABLE;

        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

        ADC_InitStructure.ADC_ExternalTrigConv = 0;

        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

        ADC_InitStructure.ADC_NbrOfConversion = 1;

        ADC_Init(ADC1, &ADC_InitStructure);

        ADC_Init(ADC2, &ADC_InitStructure);

        ADC_Init(ADC3, &ADC_InitStructure);

        

        /* ADC1 regular channel0 configuration *************************************/

      ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);

        

        /* ADC2 regular channel15 configuration *************************************/

      ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 1, ADC_SampleTime_3Cycles);

        

        /* ADC3 regular channel10 configuration *************************************/

      ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

        

        ADC_Cmd(ADC1,ENABLE);

       

    ADC_Cmd(ADC2,ENABLE);

       

    ADC_Cmd(ADC3,ENABLE);

        ADC_ContinuousModeCmd(ADC1,ENABLE);

        ADC_DMACmd(ADC1,ENABLE);

        ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

        ADC_SoftwareStartConv(ADC1);

    }

    /****************************************************/

    Tesla DeLorean
    Guru
    November 26, 2013
    Posted on November 26, 2013 at 17:07

    __IO uint16_t ADCConvertedValue[3];

    So ZERO based array elements in ADCConvertedValue[0] ADCConvertedValue[1] ADCConvertedValue[2] Quoted

    #include ''stm32f4_discovery.h''
    #include ''rcc.h''
    #include ''ADC.h''
    #include ''DMA.h''
    int main(void)
    { 
    //RCC Configuration
    RCC_Config();
    //GPIO Configuration
    GPIO_Config();
    //DMA Configuration
    DMA_Config(); 
    //ADC Configuration
    ADC_Config();
    while (1)
    { }
    }
    /****************************************************/
    void GPIO_Config(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    /* Configure ADC1 Channel0 pin as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* Configure ADC2 Channel15 pin as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    /* Configure ADC3 Channel10 pin as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    } 
    /****************************************************/
    #define CDR_ADDRESS ((uint32_t)0x40012308)
    __IO uint16_t ADCConvertedValue[3];
    void DMA_Config(void)
    {
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)CDR_ADDRESS;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & ADCConvertedValue;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = 3;
    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_PeripheralBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream0,ENABLE);
    }
    /****************************************************/
    void ADC_Config(void)
    {
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    /* ADC Common Init **********************************************************/
    ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1 ; 
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInit(&ADC_CommonInitStructure);
    /* ADC1 Init ****************************************************************/
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_ExternalTrigConv = 0;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(ADC1, &ADC_InitStructure);
    ADC_Init(ADC2, &ADC_InitStructure);
    ADC_Init(ADC3, &ADC_InitStructure);
    /* ADC1 regular channel0 configuration *************************************/
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);
    /* ADC2 regular channel15 configuration *************************************/
    ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 1, ADC_SampleTime_3Cycles);
    /* ADC3 regular channel10 configuration *************************************/
    ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
    ADC_Cmd(ADC1,ENABLE);
    ADC_Cmd(ADC2,ENABLE);
    ADC_Cmd(ADC3,ENABLE);
    ADC_ContinuousModeCmd(ADC1,ENABLE);
    ADC_DMACmd(ADC1,ENABLE);
    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
    ADC_SoftwareStartConv(ADC1);
    }
    /****************************************************/

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    November 26, 2013
    Posted on November 26, 2013 at 17:27

    PC0 Channel 10 is a poor choice on the STM32F4-Discovery, PC1 Channel 11 (ADC123_11) might be a better one. Refer to board documentation.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tapankaew.Sarod
    Associate
    November 26, 2013
    Posted on November 26, 2013 at 17:42

    I have changed to PC1 (ADC_chanal 11) but still doesn't work.The convert value alignment correct at frist time but it mess up on second request.Thank you for your answer 0690X0000060MnuQAE.gif.ToT

    Tesla DeLorean
    Guru
    November 26, 2013
    Posted on November 26, 2013 at 18:25

    ''Doesn't Work'' is hard for me to quantify, what does this mean in actual measurements vs physical state of the pins.

    A 3 cycle sample time is very short, you are in continuous/circular mode, measurements are going to be flooding in. You're going to have to use some more care in handling the results to insure the values you are using are in fact contemporaneous with each other. This will require a larger buffer, and HT/TC interrupt handling to handle values before new ones arrive.

    In terms of validating the three ADC results, and that they are in the buffer correctly one could tie each to a unique fix source. Subsequent testing could look at specific phase relationships between them.

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