AnsweredAssumed Answered

ADC scan mode problem, STM32F407

Question asked by grimes.robert on Jun 16, 2014
Latest reply on Jun 16, 2014 by grimes.robert
Hi,
I am trying to configure ADC1 and ADC3, each with six inputs.  I want each ADC to scan their respective six channels each time they are triggered by TIM2.  I want TIM2 to trigger these scans at about 152,000 Hz (about because 152 kHz is not exactly realizable).  I am trying to use DMA2_Stream0, channel 0, for ADC1, and DMA2_Stream1, channel 2, for ADC3.

I based my code on this posting by clive1: https://my.st.com/6f2f29eb

Everything appears to be correct, except the operation!  Both ADCs acquire a sample for their first four channels, and refuse to continue.  Because of this, the DMAs don't generate any interrupts.  Most interesting, TIM2 generates no interrupts at all, which is likely the problem.  However, I just can't see it!

Here is the code, which is designed for an STM32F3240G-EVAL board:

#include "stm32f4xx.h"
#include "stm324xg_eval.h"

#define SAMPLES_BUFFER_HALF  912
#define SAMPLES_BUFFER  (SAMPLES_BUFFER_HALF * 2)

__IO uint16_t adcBankA[SAMPLES_BUFFER];
__IO uint16_t adcBankB[SAMPLES_BUFFER];

void DMA2_Stream0_IRQHandler(void)
{
  if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_HTIF0)) {
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_HTIF0);
    STM_EVAL_LEDOff(LED1);
  }
 
  if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0)) {
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
    STM_EVAL_LEDOn(LED1);
  }
}

void DMA2_Stream1_IRQHandler(void)
{
  if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF0)) {
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF0);
    STM_EVAL_LEDOff(LED2);
  }
 
  if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF0)) {
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF0);
    STM_EVAL_LEDOn(LED2);
  }
}

void TIM2_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM2, TIM_IT_Trigger) != RESET) {
    TIM_ClearITPendingBit(TIM2, TIM_IT_Trigger);
    STM_EVAL_LEDToggle(LED3);
  }
}
 
void adcInit()
{
  ADC_CommonInitTypeDef acinit;
  ADC_InitTypeDef ainit;
  DMA_InitTypeDef dinit;
  GPIO_InitTypeDef ginit;
  NVIC_InitTypeDef ninit;
  TIM_TimeBaseInitTypeDef tinit;

  //---------- RCC configuration -----------------------------------------------
  
  // Enable peripheral clocks
  RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_DMA2  | RCC_AHB1Periph_GPIOA
                         | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF
                         | RCC_APB1Periph_TIM2, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC3,  ENABLE);

  //---------- GPIO configuration ----------------------------------------------
  
  ginit.GPIO_Pin = GPIO_Pin_7;
  ginit.GPIO_Mode = GPIO_Mode_AN;
  ginit.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOA, &ginit);
  ginit.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 
                 | GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_Init(GPIOC, &ginit);
  ginit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9
                 | GPIO_Pin_10;
  GPIO_Init(GPIOF, &ginit);

  //---------- NVIC configuration ----------------------------------------------
 
  /* Enable the DMA Stream IRQ Channel */
  ninit.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  ninit.NVIC_IRQChannelPreemptionPriority = 0;
  ninit.NVIC_IRQChannelSubPriority = 0;
  ninit.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&ninit);
  ninit.NVIC_IRQChannel = DMA2_Stream1_IRQn;
  ninit.NVIC_IRQChannelPreemptionPriority = 0;
  ninit.NVIC_IRQChannelSubPriority = 0;
  ninit.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&ninit);

  // Enable the TIM2 gloabal Interrupt
  ninit.NVIC_IRQChannel = TIM2_IRQn;
  ninit.NVIC_IRQChannelPreemptionPriority = 0;
  ninit.NVIC_IRQChannelSubPriority = 0;
  ninit.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&ninit);



  //---------- TIM configuration -----------------------------------------------

  /* Time base configuration */
  TIM_TimeBaseStructInit(&tinit);
  tinit.TIM_Period = (84000000 / 553) - 1; // 152 KHz
  tinit.TIM_Prescaler = 0;
  tinit.TIM_ClockDivision = 0;
  tinit.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &tinit);
 
  /* TIM2 TRGO selection */
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO
  TIM_ITConfig(TIM2, TIM_IT_Trigger, ENABLE);

  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);

  //---------- DMA configuration -----------------------------------------------

  // DMA2 Stream0 channel0 configuration for ADC1
  dinit.DMA_Channel = DMA_Channel_0; 
  dinit.DMA_Memory0BaseAddr = (uint32_t)&adcBankA;
  dinit.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
  dinit.DMA_DIR = DMA_DIR_PeripheralToMemory;
  dinit.DMA_BufferSize = SAMPLES_BUFFER_HALF;
  dinit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  dinit.DMA_MemoryInc = DMA_MemoryInc_Enable;
  dinit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  dinit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  dinit.DMA_Mode = DMA_Mode_Circular;
  dinit.DMA_Priority = DMA_Priority_High;
  dinit.DMA_FIFOMode = DMA_FIFOMode_Enable;         
  dinit.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  dinit.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  dinit.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &dinit);
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
  DMA_Cmd(DMA2_Stream0, ENABLE);

  // DMA2 Stream1 channel2 configuration for ADC3
  dinit.DMA_Channel = DMA_Channel_2; 
  dinit.DMA_Memory0BaseAddr = (uint32_t)&adcBankB;
  dinit.DMA_PeripheralBaseAddr = (uint32_t)&ADC3->DR;
  dinit.DMA_DIR = DMA_DIR_PeripheralToMemory;
  dinit.DMA_BufferSize = SAMPLES_BUFFER_HALF;
  dinit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  dinit.DMA_MemoryInc = DMA_MemoryInc_Enable;
  dinit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  dinit.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  dinit.DMA_Mode = DMA_Mode_Circular;
  dinit.DMA_Priority = DMA_Priority_High;
  dinit.DMA_FIFOMode = DMA_FIFOMode_Enable;         
  dinit.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  dinit.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  dinit.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream1, &dinit);
  DMA_ITConfig(DMA2_Stream1, DMA_IT_TC | DMA_IT_HT, ENABLE);
  DMA_Cmd(DMA2_Stream1, ENABLE);

  //---------- ADC configuration -----------------------------------------------
  
  // ADC Common Init 
  acinit.ADC_Mode = ADC_Mode_Independent;
  acinit.ADC_Prescaler = ADC_Prescaler_Div2;
  acinit.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  acinit.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&acinit);

  // ADC1 regular channels 10, 11 configuration 
  ainit.ADC_Resolution = ADC_Resolution_12b;
  ainit.ADC_ScanConvMode = ENABLE;
  ainit.ADC_ContinuousConvMode = DISABLE;
  ainit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
  ainit.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
  ainit.ADC_DataAlign = ADC_DataAlign_Right;
  ainit.ADC_NbrOfConversion = 6;
  ADC_Init(ADC1, &ainit);

  // ADC1 regular channel configuration
  ADC_RegularChannelConfig(ADC1, ADC_Channel_7,  1, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 5, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 6, ADC_SampleTime_3Cycles);

  // ADC3 regular channel configuration
  ainit.ADC_Resolution = ADC_Resolution_12b;
  ainit.ADC_ScanConvMode = ENABLE;
  ainit.ADC_ContinuousConvMode = DISABLE;
  ainit.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
  ainit.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
  ainit.ADC_DataAlign = ADC_DataAlign_Right;
  ainit.ADC_NbrOfConversion = 6;
  ADC_Init(ADC3, &ainit);

  // ADC3 regular channels 11, 12 configuration
  ADC_RegularChannelConfig(ADC3, ADC_Channel_4,  1, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_6,  2, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_5,  3, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_7,  4, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_8,  5, ADC_SampleTime_3Cycles);
  ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 6, ADC_SampleTime_3Cycles);

  // Enable ADC1
  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
  ADC_DMACmd(ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE);
  ADC_SoftwareStartConv(ADC1);

  // Enable ADC3 
  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
  ADC_DMACmd(ADC3, ENABLE);
  ADC_Cmd(ADC3, ENABLE);
  ADC_SoftwareStartConv(ADC3);
}

int main()
{
  STM_EVAL_LEDInit(LED1);
  STM_EVAL_LEDInit(LED2);
  STM_EVAL_LEDInit(LED3);
  adcInit();
  
  while (1) ;
}

Outcomes