Skip to main content
pano
Associate II
October 21, 2014
Question

STM32F4 ADC multiple channel

  • October 21, 2014
  • 6 replies
  • 1258 views
Posted on October 21, 2014 at 16:40

Hi,

I was looking for an example about ADC with 2 input pin and I have found this code, from another old thread in this forum:

#include <
stdio.h
>
#include <
stdlib.h
>
#include <
string.h
>
#include ''stm32f4xx.h''
//******************************************************************************
volatile uint16_t ADCConvertedValues[2];
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Configure ADC1 Channel3 & 5 pins as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//******************************************************************************
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* Enable peripheral clocks *************************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA2_Stream0 channel0 configuration **************************************/
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 2;
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_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel configuration ******************************/
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_480Cycles); // PA3
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_480Cycles); // PA5
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);
}
//******************************************************************************
int main(void)
{
GPIO_Configuration();
ADC1_Configuration();
puts(''ADC Testing'');
while(1)
{
if (ADCConvertedValues[1] != 0xFFFF)
{
printf(''%03X %03X\n'', ADCConvertedValues[0], ADCConvertedValues[1]);
ADCConvertedValues[1] = 0xFFFF;
}
}
while(1); /* Infinite loop */
}

I have main.c and ADC.c like different files; how to fix the previous code to read the two converted values in the main.c file? thanks
    This topic has been closed for replies.

    6 replies

    Tesla DeLorean
    Guru
    October 21, 2014
    Posted on October 21, 2014 at 18:11

    I was looking for an example about ADC with 2 input pin and I have found this code, from another old thread in this forum:

     

    ...

     

    I have main.c and ADC.c like different files; how to fix the previous code to read the two converted values in the main.c file?

     

    Ok, code looks very familiar, pity you don't cite the thread you lifted it from, what's the question here? How do you create a project with multiple files? How do you copy/merge functions between files?

    The example uses DMA to read two samples continuously into memory, in the background.

    You'd need to think about your toolchain/IDE. You'd need to think about how you need the data, whether you want it paced, or if you want an interrupt when the samples are ready, or if you want to accumulate a larger number of samples.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    pano
    panoAuthor
    Associate II
    October 22, 2014
    Posted on October 22, 2014 at 12:19

    Ok, then:

    now, I'm using this code for an ADC

    #include ''stm32f4xx_adc.h''
    #include ''stm32f4xx_gpio.h''
    #include ''stm32f4xx_rcc.h''
    #include ''ADC.h''
    void adc_configure(void){
    ADC_InitTypeDef ADC_init_structure; //Structure for adc confguration
    GPIO_InitTypeDef GPIO_initStructre; //Structure for analog input pin
    //Clock configuration
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//The ADC1 is connected the APB2 peripheral bus thus we will use its clock source
    RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOCEN,ENABLE);//Clock for the ADC port!! Do not forget about this one ;)
    //Analog pin configuration
    GPIO_initStructre.GPIO_Pin = GPIO_Pin_0;//The channel 10 is connected to PC0
    GPIO_initStructre.GPIO_Mode = GPIO_Mode_AN; //The PC0 pin is configured in analog mode
    GPIO_initStructre.GPIO_PuPd = GPIO_PuPd_NOPULL; //We don't need any pull up or pull down
    GPIO_Init(GPIOC,&GPIO_initStructre);//Affecting the port with the initialization structure configuration
    //Analog pin configuration
    GPIO_initStructre.GPIO_Pin = GPIO_Pin_1;//The channel 11 is connected to PC1
    GPIO_initStructre.GPIO_Mode = GPIO_Mode_AN; //The PC1 pin is configured in analog mode
    GPIO_initStructre.GPIO_PuPd = GPIO_PuPd_NOPULL; //We don't need any pull up or pull down
    GPIO_Init(GPIOC,&GPIO_initStructre);//Affecting the port with the initialization structure configuration
    //ADC structure configuration
    ADC_DeInit();
    ADC_init_structure.ADC_DataAlign = ADC_DataAlign_Right;//data converted will be shifted to right
    ADC_init_structure.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit number giving a maximum value of 4096
    ADC_init_structure.ADC_ContinuousConvMode = ENABLE; //the conversion is continuous, the input data is converted more than once
    ADC_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;// conversion is synchronous with TIM1 and CC1 (actually I'm not sure about this one :/)
    ADC_init_structure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//no trigger for conversion
    ADC_init_structure.ADC_NbrOfConversion = 1;//I think this one is clear :p
    ADC_init_structure.ADC_ScanConvMode = DISABLE;//The scan is configured in one channel
    ADC_Init(ADC1,&ADC_init_structure);//Initialize ADC with the previous configuration
    //Enable ADC conversion
    ADC_Cmd(ADC1,ENABLE);
    //Select the channel to be read from
    ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_144Cycles);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_144Cycles);
    }
    int adc_convert(void){
    ADC_SoftwareStartConv(ADC1);//Start the conversion
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion
    return ADC_GetConversionValue(ADC1); //Return the converted data
    }

    and in the main file

    ConvertedValue = adc_convert();

    Now, I need another analog input (for a force sensor); I have no idea how to do this, so, looking in this forum I have founded [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/Multi%20Channel%20ADC%20reading&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=3075]this 3d with your code. The previous code has the function

    int adc_convert(void)

    that I can use to have the converted value in the main fuction. If I copy the code of the mutiple channel ADC and then copy the code about main fuction

    GPIO_Configuration();
    ADC1_Configuration();
    puts(''ADC Testing'');
    while(1)
    {
    if (ADCConvertedValues[1] != 0xFFFF)
    {
    printf(''%03X %03
    X'', ADCConvertedValues[0], ADCConvertedValues[1]);
    ADCConvertedValues[1] = 0xFFFF;
    }
    }
    while(1); /* Infinite loop */
    }

    it doesn't works because main function doesn't know what

    ADCConvertedValues

    is.
    frankmeyer9
    Associate III
    October 22, 2014
    Posted on October 22, 2014 at 12:48

    ..it doesn't works because main function doesn't know what

    ADCConvertedValues

    is That's probably because your mastering of the C language seems not quite sufficient. Have you heard of the

    extern

    keyword ?
    Tesla DeLorean
    Guru
    October 22, 2014
    Posted on October 22, 2014 at 15:38

    Define it in one file, and then use the external reference in the other(s)

    extern volatile uint16_t ADCConvertedValues[2];

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    pano
    panoAuthor
    Associate II
    October 24, 2014
    Posted on October 24, 2014 at 12:56

    ok thanks;

    to resolve this errors?

    .\output\controllo_mot.axf: Error: L6218E: Undefined symbol DMA_Cmd (referred from adc.o).

    .\output\controllo_mot.axf: Error: L6218E: Undefined symbol DMA_DeInit (referred from adc.o).

    .\output\controllo_mot.axf: Error: L6218E: Undefined symbol DMA_Init (referred from adc.o).
    Tesla DeLorean
    Guru
    October 24, 2014
    Posted on October 24, 2014 at 14:17

    Add stm32f4xx_dma.c to your project, review project templates.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..