2012-12-20 08:27 AM
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.2012-12-21 01:24 AM
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.2012-12-21 01:35 AM
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.2012-12-21 01:43 AM
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>© 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****/
2012-12-21 04:05 AM
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.2012-12-21 07:38 AM
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, Hal2012-12-21 11:13 AM
I think I found it, you can't enable multiple channels in single NVIC_Init call, you need to enable each channel individually.
2013-01-02 01:12 AM
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. Tobaird.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 :). Jerome2013-01-02 07:48 AM
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, Hal2013-01-02 08:32 AM
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?