AnsweredAssumed Answered

STM32F4 ADC1 + ADC3, dual or tripple mode?

Question asked by Martin on Oct 14, 2013
Latest reply on Oct 14, 2013 by Martin
Hello,

I want to sample 3 channels on ADC1 and 2 channels on ADC3. Does i have the ADCs to use in dual or tripple mode?

The following Code does not work :-(

/*
    Sample Temp, VRef, VBat and ports PF9, PF10 using DMA and
    trigger via Timer3 at 2 Hz
*/
 
#define BUFFERLENGTH       5
static __IO uint16_t ADCConvertedValues[BUFFERLENGTH];
 
__IO uint8_t  g_Valid                   = 0;
 
void DMA2_Stream0_IRQHandler()
{
  if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
    {
        DMA_ClearITPendingBit(DMA2_Stream0,  DMA_IT_TCIF0);
        g_Valid = 1;
    }
  if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TEIF0) != RESET)
    {
        DMA_ClearITPendingBit(DMA2_Stream0,  DMA_IT_TEIF0);
    }
}
 
void SENSORS_Init (void)
{
    NVIC_InitTypeDef                NVIC_InitStructure;
  DMA_InitTypeDef           DMA_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef           TIM_OCInitStructure;
  ADC_InitTypeDef           ADC_InitStructure;
  ADC_CommonInitTypeDef     ADC_CommonInitStructure;
    GPIO_InitTypeDef            GPIO_InitStructure;
     
  /* Timer3, ADC1 und DMA2 clocks einschalten */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
   
    /* PF9 und PF10 als Analog Eingang */
    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
     
    /* Interrupts im NVIC freigeben */
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
    NVIC_Init(&NVIC_InitStructure);
 
    /* DMA Aufsetzen */
  /* DMA2 Stream0 channel0 Konfiguration */
    /* Init auf Standardwerte setzen */
    DMA_StructInit(&DMA_InitStructure);
  DMA_DeInit(DMA2_Stream0);
    /* Kanal 0 */
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    /* Adresse des ADC Datenregisters (Quelle) */
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)0x40012308; // &ADC1->DR;
    /* Adresse der Datenstruktur (Ziel) */
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) ADCConvertedValues;
    /* Richtung des Transfers */
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    /* Länge des Datentransfers */
  DMA_InitStructure.DMA_BufferSize = BUFFERLENGTH;
    /* Die Quelladresse ändert sich nicht */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    /* Die Zieladresse muss sich mit jedem Wert ändern */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    /* Größe einer Datenübertragung (Quelle, 16 Bit) */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    /* Größe einer Datenübertragung (Ziel, 16 Bit) */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    /* Datenübertragungen immer wieder von vorne anfangen */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    /* Daten mit hoher Priorität übertragen */
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    /* Direkte Datenübertragung */
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    /* Don't care, da Fifo abgeschaltet */
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    /* Werte einzeln in Speicher übertragen */
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    /* Werte einzeln vom ADC lesen */
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    /* DMA Initialisieren */
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
 
    /* DMA Interrupt aktivieren */
    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
 
    /* DMA starten */
  DMA_Cmd(DMA2_Stream0, ENABLE);
     
    /* Timer aufsetzen */
    // Timer aus
    TIM_Cmd(TIM3, DISABLE);
    TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);
 
    // Der 16 Bit Timer 3 hängt am APB1 mit 42MHz, Timertakt ist damit 84 MHz
    // 84MHz   / 7000 (Prescaler) = 12000 Hz
    // 12000Hz / 6000 (Period)    = 2Hz
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 7000-1;
    TIM_TimeBaseStructure.TIM_Prescaler = 6000-4;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 
    /* TIM3 channel2 configuration in PWM mode */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;               
    TIM_OCInitStructure.TIM_Pulse = 1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;        
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
 
    /* TIM3 enable counter */
    TIM_Cmd(TIM3, ENABLE); 
     
    /* ADC aufsetzen */
    ADC_CommonStructInit(&ADC_CommonInitStructure);
    ADC_DeInit();
  ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult; // ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; // ADC_DMAAccessMode_Disabled;
    /* Delay zwischen 2 Sampling Phasen */
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);
 
  /* ADC1 Init */
    ADC_StructInit(&ADC_InitStructure);
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    /* Kontinuierlich samplen */
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    /* Kein Trigger */
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; // ADC_ExternalTrigConvEdge_None;
  // ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_CC1;
    /* Daten Rechtsbündig ablegen */
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 3; // BUFFERLENGTH;
  ADC_Init(ADC1, &ADC_InitStructure);
  ADC_InitStructure.ADC_NbrOfConversion = 2; // BUFFERLENGTH;
  ADC_Init(ADC3, &ADC_InitStructure);
 
  /* ADC1 regular channel18 (VBAT) & channel16 (TempSensor) configuration *****/
    // TODO: 480 Cycles erklären und ggf anpassen
  ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 2, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_Vrefint, 3, ADC_SampleTime_480Cycles);
 
  ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_480Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 1, ADC_SampleTime_480Cycles);
 
  /* Enable VBAT channel: channel18 */
  ADC_VBATCmd(ENABLE);
 
  /* Enable TempSensor and Vrefint channels: channel16 and channel17 */
  ADC_TempSensorVrefintCmd(ENABLE);
 
  /* Enable DMA request after last transfer (Single-ADC mode) */
  // ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
     
    ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
    /* Enable STM32_TEMPSENS_ADC_DEVICE EOC interupt. */
    //ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
     
  /* Enable ADC1 DMA */
  //ADC_DMACmd(ADC1, ENABLE);
  //ADC_DMACmd(ADC3, ENABLE);
 
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  ADC_Cmd(ADC3, ENABLE);
     
    /* Start ADC1 */
    //ADC_SoftwareStartConv(ADC1);
}


Martin

Outcomes