cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 ADC_TripleMode_RegSimult

yayi
Associate II
Posted on December 20, 2012 at 17:27

Hi,

I am trying to use the 3 ADC in simultaneous mode.

I receive correctly every data but I am not able to catch any interruption in order to drive data on the good place. When I have my table I want to dispatch adc_channel_1to a table, adc_channel_2 to a other table etc...

But I have no interruption.

Here is my code to init DMA:

void DMA_Config(void)

{

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

 

  /* DMA2 Stream0 channel0-11-12 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_0; 

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCTripleConvertedDemiVal;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 180;

  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_Enable;        

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

 

 /**  Test de l'interruption sur la fin du transfert **/

 DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE, ENABLE);

  /* DMA2_Stream0 enable */

  DMA_Cmd(DMA2_Stream0, ENABLE);

} My code to init GPIO:

void ADC_Gpio_Config(void)

{

  /* Enable peripheral clocks */

  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);

  

 /* Configure ADC Channel 0 - 3 - 4 - 5 pin as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;

  //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

 /* Configure ADC Channel 6 - 8 - 9 pin as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8 | GPIO_Pin_9;

  //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

 

 /* Configure ADC Channel 10 - 12 - 13 pin as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_13;

  //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}

And my code to init ADC:

void ADC_Config(void)

{

 ADC_Gpio_Config();

 DMA_Config();

 

 /* Enable peripheral clocks */

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |

                         RCC_APB2Periph_ADC3, ENABLE);

 

/*******************************************************************************/

/*  ADCs configuration: triple simultaneous with 10cycles delay   */

/*******************************************************************************/ 

 /* ADC Common Init */

  ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult ;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

/**< ADC1 regular channels 0 and 3 and 4 (and 5) configuration */

 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_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 3;

  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channels 0 and 3 and 4 (and 5) configuration */

  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_3Cycles);

 ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_3Cycles);

// ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 4, ADC_SampleTime_15Cycles);

 

/**< ADC2 regular channels 6 and 8 and 9 configuration */

  ADC_Init(ADC2, &ADC_InitStructure);

  /* ADC2 regular channels 6 and 8 and 9 configuration */

  ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 1, ADC_SampleTime_3Cycles);

  ADC_RegularChannelConfig(ADC2, ADC_Channel_8, 2, ADC_SampleTime_3Cycles);

 ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 3, ADC_SampleTime_3Cycles);

 

/**< ADC3 regular channels 10, 12 and 13 configuration */

  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channels 10, 12 and 13 configuration */

  ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

  ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);

 ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_3Cycles);

 

 /* Enable EOC Interrupt */

 ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

 

 /* Enable DMA request after last transfer (Multi-ADC mode)  */

  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

 

 /* Enable ADC1 & ADC2 & ADC3 */

  ADC_Cmd(ADC1, ENABLE);

 ADC_Cmd(ADC2, ENABLE);

 ADC_Cmd(ADC3, ENABLE);

} And my handler:

void ADC1_IRQHandler(void)

{

 cptADCIt++;

}

void DMA2_Stream0_IRQHandler(void)

{

 DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0 | DMA_IT_TEIF0);

 cptDMAIt++;

}

The cptXXXIt never increase...

Can someone help me?

Thanks.

18 REPLIES 18
zzdz2
Associate II
Posted on December 21, 2012 at 10:24

That's strange, are you getting any interrupt at all?

Maybe interrupts are disabled globally, you can use something like __enable_irq(); to make sure it's enabled.

yayi
Associate II
Posted on December 21, 2012 at 10:35

SysTick & RCC interrupts work fine.

I don't understand what you mean with the __enable_irq();  function?

Do I create a function to enable  IRQ despite do it in my main? Or check NVIC register?

I do that :

   NVIC_InitStructure.NVIC_IRQChannel = RCC_IRQn | ADC_IRQn | DMA2_Stream0_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

Edit : Correction, my RCC doesn't work anymore ... I don't understand why.

Edit 2: I think RCC it is good working. I think I just don't clearly understand RCC It. Because in example the IT never tick, so I think it works.
yayi
Associate II
Posted on December 21, 2012 at 10:43

Here is my main.c:

Not very clear because I do lot of try to understand what works or not.

/**

  ******************************************************************************

  * @file    ST/main.c

  * @author  J. YAYI

  * @date    12-Déc-2012

  * @brief   Main program body

  ******************************************************************************

  * @attention

  *

  *

  * <h2><center>&copy; COPYRIGHT 2012 AKA AUTOMATISME</center></h2>

  ****************************************************************************** 

  */

/* Includes ------------------------------------------------------------------*/

#include <main.h>

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

__IO uint32_t     msTicks;

__IO uint32_t     cptFlagDMA;

__IO uint32_t     cptFlagOVR;

__IO uint32_t     cptADCIt;

__IO uint32_t     cptDMAIt;

__IO uint32_t     cptErrDMA;

__IO uint32_t     cptSysTick;

__IO uint32_t     flagADC1;

__IO uint32_t     flagADC2;

__IO uint32_t     flagADC3;

__IO uint32_t     i;

__IO uint32_t     ADCTripleConvertedValue[18];

__IO uint32_t     ADCTripleConvertedVal[18];     /**< Tableau contenant la valeur des ADC */

ADC_InitTypeDef       ADC_InitStructure;     /**< Structure d'initialisation des ADC */

ADC_CommonInitTypeDef ADC_CommonInitStructure;  /**< Structure d'initialisation générale des ADC */

DMA_InitTypeDef       DMA_InitStructure;     /**< Structure d'initialisation du DMA */

GPIO_InitTypeDef      GPIO_InitStructure;     /**< Structure d'initialisation des GPIO */

NVIC_InitTypeDef    NVIC_InitStructure;     /**< Structure d'initialisation des interruptions */

RCC_ClocksTypeDef   RCC_ClockFreq;       /**< Structure pour récupérer les différentes horloges */

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

/**

  * @brief  Main program

  * @param  None

  * @retval None

  */

int main(void)

{

 /* Initialize LEDs mounted on STM32F4-Discovery board ***********************/

 Hard_LEDInit();

 

 /* Turn on LED4 and LED5 - detect le bon démarrage *************************/

 Hard_LEDOn(LED4);

 Hard_LEDOn(LED5);

 

  /* This function fills the RCC_ClockFreq structure with the current

  frequencies of different on chip clocks (for debug purpose) **************/

  RCC_GetClocksFreq(&RCC_ClockFreq);

 

 RCC_Config();

 

 /* SysTick end of count event each 1ms */ 

 //SysTick_Config(RCC_ClockFreq.HCLK_Frequency / 10000);

 

 /* Enable and configure RCC global IRQ channel, will be used to manage HSE ready

  and PLL ready interrupts.

  These interrupts are enabled in stm32f4xx_it.c file **********************/

   NVIC_InitStructure.NVIC_IRQChannel = RCC_IRQn | ADC_IRQn | DMA2_Stream0_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

 

 /**< Paramètre les ADC1, 2 & 3, avec les channels 10, 11 & 12. Les ADCs sont ENABLE */

 ADC_Config();

 

 while (!DMA_GetCmdStatus(DMA2_Stream0))

 {

  cptErrDMA++;

 }

 /* Start ADC1 Software Conversion */

  ADC_SoftwareStartConv(ADC1);

 

 

 while(1)/**< Boucle Infinie // Infinite Loop */

 {

  //Détection des problèmes d'overrun

  if ( ADC_GetFlagStatus(ADC1, ADC_FLAG_OVR) | ADC_GetFlagStatus(ADC2, ADC_FLAG_OVR) | ADC_GetFlagStatus(ADC2, ADC_FLAG_OVR) )

  {

   ADC_ClearFlag(ADC1, ADC_FLAG_OVR);

   ADC_ClearFlag(ADC2, ADC_FLAG_OVR);

   ADC_ClearFlag(ADC3, ADC_FLAG_OVR);

   cptFlagOVR++;

  }

  

  

  if ( ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) )

  {

   ADC_ClearFlag(ADC2, ADC_FLAG_EOC);

   flagADC2++;

  }

  

  if ( ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) )

  {

   ADC_ClearFlag(ADC3, ADC_FLAG_EOC);

   flagADC3++;

  }

  

  // Récup du statut du flag de transfert !!

  if ( DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0) )

  {

   DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0);

   cptFlagDMA++;

  }

  

  ADCTripleConvertedVal[0] = ADCTripleConvertedValue[0];

  ADCTripleConvertedVal[1] = ADCTripleConvertedValue[1];

  ADCTripleConvertedVal[2] = ADCTripleConvertedValue[2];

  

  

  i++;

 }

}

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *   where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

{

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  /* Infinite loop */

  while (1)

  {

  }

}

#endif

/******************* (C) COPYRIGHT 2012 AKA AUTOMATISME *****END OF FILE****/

zzdz2
Associate II
Posted on December 21, 2012 at 13:05

When using F1 device __enable_irq() is defined in 'core_cm3.h'.

You can use __enable_irq()/__disable_irq() to enable/disable all irqs, it seems enabled by default but who knows.

If you have any irq working then it's not the problem.

raptorhal2
Lead
Posted on December 21, 2012 at 16:38

2 comments:

The first post uses ADCTripleConvertedDemiVal[18], this main uses ADCTripleConvertedValue[18]

When conversion is complete, there  should be 9 values available, not 3.

Cheers, Hal

zzdz2
Associate II
Posted on December 21, 2012 at 20:13

I think I found it, you can't enable multiple channels in single NVIC_Init call, you need to enable each channel individually.

yayi
Associate II
Posted on January 02, 2013 at 10:12

Hello, and I wish you a Happy New Year!!!

Sorry for my late response I was in vacation....

So knik you are right I have to use different NVIC_Init(...) function separately to activate ADC, and DMA interrupt.

It is very strange but, why not. I am able to detect any ADC interrupt in order to sort my analog data.

To

baird.hal.001

, has I said it is a draft of my code with a lot of test in order to check capacity and to understand how it works.

I will try to post a correct code for example as soon as every things works fine :).

Jerome

raptorhal2
Lead
Posted on January 02, 2013 at 16:48

So knik your are right I have to use different NVIC_Init(...) function separately to activate ADC, and DMA interrupt. It is very strange but, why not.

Not so strange when you think about it. Typically, each interrupt will have a unique priority/subpriority combination.

Cheers, Hal

yayi
Associate II
Posted on January 02, 2013 at 17:32

Hello,

I have an other trooble...

Interrupt works fine but I don't understand how works DMA in simulataneous mode (DMA mode 1)...

I use 9 channels :

ADC1 :

ch0 - ch3 - ch4

ADC2 :

ch6 - ch8 - ch9

ADC3:

ch10 - ch12 - ch13

The order of my table should be :

ch0 - ch6 - ch10 - ch3 - ch8 - ch12 - ch4 - ch9 - ch13

At the start everythings works fine but after some loop I have a displacement of the measure.

So in my table the ch0 is in adress 5...

Can someone explain me why?