AnsweredAssumed Answered

ADC and DAC Issues with STM32F4VGT6

Question asked by amratia.kishan on Sep 11, 2014
Latest reply on Sep 12, 2014 by fm
Hi, 

I am using trying to use the ADCs on the STM32f4vgt6 with the DMA Controller in continuous conversion mode. I have this chip mounted on a custom board and I am using 8 ADC channels. Below is my initialization code:
 
uint16_t ADC_Values[1];
 
void adc_init(void)
{
  
  GPIO_InitTypeDef      GPIO_InitStructure;
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
   
  GPIO_StructInit(&GPIO_InitStructure);
  ADC_StructInit(&ADC_InitStructure);
  ADC_CommonStructInit(&ADC_CommonInitStructure);
  DMA_StructInit(&DMA_InitStructure);
  
  // Setup Peripheral Clocks
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
  
  // GPIO Pin Configuration in Analog Mode
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
   
  //Configure DMA2, Stream4 on Channel 0
  DMA_DeInit(DMA2_Stream4);
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_Values[0];
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 1;
  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_Stream4, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream4, ENABLE);
   
  
  ADC_DeInit();
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_Init(ADC1,&ADC_InitStructure);
   
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  //ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; // Dont need this in Independant ADC Mode
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInit(&ADC_CommonInitStructure);
   
    ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_480Cycles);
       
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);  // Causing ADC to read 0xFFF if Continuous Conversion mode is enabled
     
  ADC_DMACmd(ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE);
   
  ADC_SoftwareStartConv(ADC1); // Start ADC1 conversion
  
}



Keep in mind that I want to actually convert on 8 channels but in the code above I am only converting on one channel to make debugging easier.


However, using the code above I have some unusual behaviour. Whenever the ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); command is present, the ADC would output 0xFFF, all the time. If commented out, the ADC would convert the value correctly but only on the first attempt after flashing the chip. And after resetting the chip, the ADC conversion value is close to the real value but never the same and never as close as the first time after flashing. Therefore after every instance that I flash the chip, I can get the correct ADC reading but not in any other scenario. 


Another interesting thing is that I turned off the Continuous conversion mode and uncommented ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);. This gave the same result whereby the ADC result would only be correct after flashing the chip.


I really don't know why this code wouldn't work. My discovery board has stopped working otherwise I would try the code on there. I have tried other ADC Channels as well with the same result. I don't know what to do anymore and any help would be appreciated. 

I also have a problem with the DAC where the output value is much lower than expected. And setting the DAC register to low values will cause the output to oscillate. Below is my DAC Code:

void DAC_init(void)
{
    DAC_InitTypeDef DAC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure ;
     
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
     
    GPIO_StructInit(&GPIO_InitStructure);
    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);
     
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);
     
    DAC_Cmd(DAC_Channel_1, ENABLE);
 
}

Thanks

Outcomes