AnsweredAssumed Answered

STM32F4 Discovery ADC

Question asked by paternoster.cedric on Feb 7, 2014
Latest reply on Feb 10, 2014 by paternoster.cedric
Hi,

It's the first time that I use the STM32F4 Discovery Board and I have a problem with the ADC.

My problem is that I use one ADC (ADC1) with 4 channels,
My config: ADC1_ch10 on PC0, ADC1_ch12 on PC2, ADC1_ch13 on PC3 and ADC1_ch4 on PA4.

I wired on a breadboard with 4 potentiometers (10k) for each channel.
When I vary the potentiometer on the channel 12 (PC2) or 13 (PC3), the obtained values are correct and vary independently.
But with the two others channels when I vary the potentiometer for the channel 10 (PC0) their values change but also that of channel 4 (PA4). 
For channel 4 (PA4), the values are correct but not that of the channel 10 (PC0) and if I vary the channel 10 (PC0) instead of 4 (PA4) the values don't change. And I have always the same problem if I change ADC1 in ADC2.

I did another test by removing the channel 10 (PC0) 
And there is the channel 4 (PA4) which changes with the channel 12 (PC2) but not the otherwise.

If we change the channel 10 (PC0) by the channel 11 (PC1), we haven't the problem but we use PC1 for another application.

Is it possible I can't use 4 channels on one ADC ?

My code:

/* ADC_Config.c*/

/* Includes ------------------------------------------------------------------*/
#include "stm32f4_discovery.h"
#include <stdio.h>
#include "compiler.h"
#include "ADC_Config.h"

/** @addtogroup STM32F4_Discovery_Peripheral_Examples
  * @{
  */

/** @addtogroup ADC_ADC3_DMA
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADC1_DR_ADDRESS     ((uint32_t)0x4001224C)
#define NBR_ADC 4
#define NB_ELEMENTS(t) (sizeof (t) / sizeof *(t))

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* You can monitor the converted value by adding the variable "ADC3ConvertedValue" 
   to the debugger watch window */

__IO uint16_t ADC1ConvertedValue[NBR_ADC];

void ADC1_DMA_Config(void)
{
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC1, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  /* DMA2 Stream0 channel0 configuration **************************************/
     DMA_InitStructure.DMA_Channel = DMA_Channel_0;
     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
     DMA_InitStructure.DMA_BufferSize = NB_ELEMENTS(ADC1ConvertedValue);
     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);
     DMA_Cmd(DMA2_Stream0, ENABLE);

    /*Configure ADC3 Channel12 pin as analog input ******************************/
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
     GPIO_Init(GPIOA, &GPIO_InitStructure);

     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
     GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* 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_ExternalTrigConv = ADC_ExternalTrigConv_Ext_IT11;
     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
     ADC_InitStructure.ADC_NbrOfConversion = NBR_ADC;
     ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC3 regular channel12 configuration *************************************/
     ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 0, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 3, ADC_SampleTime_480Cycles);

 /* 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);

     ADC_SoftwareStartConv(ADC1);
}

static void GetADCvalue(adcRegister_t *value)
{
#define NMB_SAMPLE     4
static adcRegister_t sum={};
static U8 i=0;

     sum.adc_1+=ADC1ConvertedValue[0];
     sum.adc_2+=ADC1ConvertedValue[1];
     sum.adc_3+=ADC1ConvertedValue[2];
     sum.adc_4+=ADC1ConvertedValue[3];

     if (i >= (NMB_SAMPLE-1))
     {
          sum.adc_1/=NMB_SAMPLE;
          sum.adc_2/=NMB_SAMPLE;
          sum.adc_3/=NMB_SAMPLE;
          sum.adc_4/=NMB_SAMPLE;

          *value=sum;
          i=0;
     }


     i++;
}

/******************************************************************************************
 * conversion adc register-> mV
 * 100%=3.3V=3300mVolt -- R= 100K et 47K
 * Pont diviseur=47k/147k (donc 10V x 47/147=3.19V max sur ADC)
 * facteur= 3300/(47/147)= 10320 pour avoir 100% ‡ 10V en entrÈe
 ******************************************************************************************/
void GetADCinRealValue(adc_real_t *adc_real)
{
static adcRegister_t value={};

     GetADCvalue (&value);

     adc_real->adc_1_mV=(value.adc_1 * 3000ul)/4096;
     adc_real->adc_2_mV=(value.adc_2 * 3000ul)/4096;
     adc_real->adc_3_mV=(value.adc_3 * 3000ul)/4096;
     adc_real->adc_4_mV=(value.adc_4 * 3000ul)/4096;
}

Sorry for my bad english.

Thanks

Outcomes