This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

STM32F3 analog-digital converter

Hello.
I am using a STM32F303 development board and i am trying to use the 4 ADCs that incorporates.My first question is it's possible to use the 4 ADCs in the same time?. I want to measure four voltages variating from 0 to 3.6v on one analog input of each ADC.If anyone has an idea about how to do, i will be very grateful.
Best Regards

  • Does the processor documentation say it has four ADC, or that it has one ADC with four different processor pins that can be multiplexed in? That will obviously be the answer to if it can measure four signals at the same time, or if you need to measure 1, then 2, then 3, then 4 then 1 again.

    A hint here is that you need to read that part of the processor documentation when you are going to write the code.

  • Thank you for the quick answer.
    Yes it has four ADCs that can work in independent or dual mode. In fact, i don't know how to configure them together because i didn't find an example about this option.
    Thus, i don't know if have to use them with DMA or not.

  • I don´t know an answer directly as well. What u could try is taking a look at the FirmWare library. For the discovery Board stm32f3 are existing Example Projects, even if due to murphy´s law with a different F3 type than your´s. AFAIK there is no example that fits directly to your issue. The librarys are controlled by using predefined Statments an filling them into init-Structures. May be if u understand the structure where and how to find the DEFINES you could set your needed init. But never the less you have to look closely to the Usermanual. I know how that pains since the f3 are widly more complex than the the f1´s...

  • Ok thanks. Otherwise, i took the ADC firmware of STM32F3 but i can't get the expected values.

    When i put 1.5V for example in my input channel i got 1.6 after conversion.
    Below the code i used, someone have an idea why ?

    #include "main.h"

    /* Private variables ---------------------------------------------------------*/

    __IO uint16_t ADC1ConvertedValue = 0; //Stores the calculated ADC value
    __IO uint16_t ADC1ConvertedVoltage = 0; // Used to store the actual voltage calculated by ADC for the 1st channel
    __IO uint16_t calibration_value = 0; // Used to store the value of the calibartion
    __IO uint32_t TimingDelay = 0;
    __IO uint32_t tabVal[512];

    // PRIVATE Variables as float
    __IO uint32_t ADC1ConvertedVoltage1 = 0; // Used to store the actual voltage calculated by ADC for the 1st channel
    __IO float tabVal1[512]; // GPIO Structure to use the GPIO functionnalities
    GPIO_InitTypeDef GPIO_InitStructure; // Declare a structure to use ADC Init structure definition
    ADC_InitTypeDef ADC_InitStructure; // we can define the mode of conversion (continuous or single, resolution, number of channels to be convertrted // Declare a structure to use ADC InitType structure definition
    ADC_CommonInitTypeDef ADC_CommonInitStructure;// define the mode ( independant or multimode)

    /* Private define ------------------------------------------------------------*/
    /** * @brief Main program. * @param None * @retval None */

    int main(void)
    { int i=0; tabVal[i]=0; /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f30x.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f30x.c file */

    /* Configure the ADC clock */ //RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2); RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div6);// added by me to bring 72Mhz/6=12 Mhz

    /* Enable ADC1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);

    /* Setup SysTick Timer for 1 µsec interrupts */ if (SysTick_Config(SystemCoreClock / 1000000)) { /* Capture error */ while (1) {} }

    /* ADC Channel configuration */ /* GPIOC Periph clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

    /* Configure ADC Channel7 as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure);

    ADC_StructInit(&ADC_InitStructure);

    /* Calibration procedure */ ADC_VoltageRegulatorCmd(ADC1, ENABLE);

    /* Insert delay equal to 10 µs */ //Delay(10); // doesn't work, stuck in debug mode, so i replaced it by nop __nop(); __nop(); __nop(); __nop(); __nop();

    ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single); ADC_StartCalibration(ADC1);

    while(ADC_GetCalibrationStatus(ADC1) != RESET ); calibration_value = ADC_GetCalibrationValue(ADC1);

    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot; ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0; ADC_CommonInit(ADC1, &ADC_CommonInitStructure);

    ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable; //ADC_ContinuousConvMode_Enable; ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0; ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable; ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable; ADC_InitStructure.ADC_NbrOfRegChannel = 1; ADC_Init(ADC1, &ADC_InitStructure);

    /* ADC1 regular channel7 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_1Cycles5);

    /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE);

    /* wait for ADRDY */ while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));

    /* Start ADC1 Software Conversion */ ADC_StartConversion(ADC1);

    /* Infinite loop */ while (1) {

    /* Test EOC flag */ while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // wait for the conversion to be end

    /* Get ADC1 converted data */ ADC1ConvertedValue =ADC_GetConversionValue(ADC1);

    /* Compute the voltage */ ADC1ConvertedVoltage = (ADC1ConvertedValue *3300)/0xFFF; // FFF=4095 because we have 12 bits of resolution //ADC1ConvertedVoltage=(ADC1ConvertedValue *3300/0xFFF); tabVal[i]=ADC1ConvertedVoltage; i++; if(i>511) i=0;

    }

    }
    /** * @brief Inserts a delay time. * @param nTime: specifies the delay time length, in milliseconds. * @retval None */
    /*void Delay(__IO uint32_t nTime)
    { TimingDelay = nTime;

    while(TimingDelay != 0);
    }*/

  • Hey,

    may be the problem is more in the value´s calculating part than in the init of the adc.
    I assume you have a Vref = 3,3V(?).
    You may have an overrun issue in your equation
    (ADC1ConvertedValue *3300)/0xFFF.

    with an inputvoltage = 1.5V the ADC1ConvertedValue would be
    1.) (1.5/3.3) * ((2^12)-1) = 1861
    2.) 1861 * 3300 = 6141300

    I don´t know enough about what the compiler is doing with the (1861 * 3300) operation. If it is performed on the ADC1ConvertedValue variable and the result is stored there you´d have an overrun problem. I don´t know if the compiler handles that by it´s own.
    So in first run try to change the ADC1ConvertedValue variable to an uint32_t and cast it back to uint16_t AFTER dividing it by 4096.

  • Hey,

    For the Vref, i don't know its value. In STM32F302xx/STM32F303xx electrical characteristics, i have noticed that Vref is connected to Vdda, so i measured with millimeter its value on stm32f3-discovery and found 3V. Then, i changed this line(ADC1ConvertedValue *3300)/0xFFF by (ADC1ConvertedValue *3000)/0xFFF. So the problem was resolved.

    I don't know if my way to proceed is correct or no...

    Otherwise, i don't understand your point 1) and 2).

  • I have a question about the ADC clock of STM32F3. In fact in the examlples given by ST configure this clock like this:

    RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1); //that's mean that the ADC is derived from the PLL Clock (72Mhz in this case). In the same time ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;
    So based on the data sheet, with this configuration has the advantage to reach the maximum of the ADC clock but it's not synchronized with the AHB clock. if i want to use timer to trigger the conversion of ADC, we have to use the AHB clock to drive the ADC clock.

    For that purpose i have configured my ADC clock like this :

    /* Configures the AHB clock (HCLK) ***/

    RCC_HCLKConfig(RCC_SYSCLK_Div1); // RCC_AHB_Clock_Source( 72MHz in this case ). Then :
    ADC_CommonInitStructure.ADC_Clock = ADC_Clock_SynClkModeDiv4; // this gives us 18 MHz

    Do you thank this configuration is correct or no ? Thank in advance of your help.