2012-10-15 05:13 AM
Hi all,
I use STM32L discovery with sample codes from standard peripheral library. I need to measure several channels continuously but the original example does not work either. After initialization only one sample is measured and no other conversion is trigerred automatically. Does anyone has a clue what I could be doing wrong? This is my code. ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; __IO uint16_t ADC_ConvertedValue[3]; void ADC_DMA_Config(void) { /*------------------------ DMA1 configuration ------------------------------*/ /* Enable DMA1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* DMA1 channel1 configuration */ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 2; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 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_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Enable DMA1 channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); /*----------------- ADC1 configuration with DMA enabled --------------------*/ /* Enable the HSI oscillator */ RCC_HSICmd(ENABLE); /* Enable GPIOB clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); /* Configure PB.12 (ADC Channel18) in analog mode */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Check that HSI oscillator is ready */ while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); /* Enable ADC1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* ADC1 configuration */ ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 2; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel18 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_21, 1, ADC_SampleTime_4Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 2, ADC_SampleTime_4Cycles); /* Enable the request after last transfer for DMA Circular mode */ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Wait until the ADC1 is ready */ while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET) { } /* Start ADC1 Software Conversion */ ADC_SoftwareStartConv(ADC1); }2012-10-15 06:27 AM
MemoryInc needs to be enabled to get the DMA to put the second converted value in the buffer second position.
Cheers, Hal2012-10-15 07:06 AM
Thank you. it is obviously true
but unfortunatelly it does not solve the problem that only one sample is converted and next conversion is not trigerred.2012-10-15 09:00 AM
I am not very familiar with the STM32L152 library, but on other processors, strange results occurred if the following was not included in the ADC initialization:
ADC_InitStructure.ADC_ExternalTrigConv = 0; Try that. If that is not the answer, perhaps someone else can spot something. Cheers, Hal2012-10-15 11:36 PM
ADC_ExternalTrigConvEdge_None is declared by define and equals to 0.
I tried also this just to be sure, but it did not help.2012-10-16 12:03 AM
I can't spot an obvious problem, too.
And, to admit that, have no much experience with the L51. I would change the initialization to an EOC interrupt for the ADC, and check with the debugger if there really just one conversion happens. I'm also lost on the internal bus structure of the L51. You might check if DMA1 is actually capable of serving the ADC. I only remember this issue from the F4, with two DMA units on different busses.2012-10-16 01:33 AM
>>MemoryInc needs to be enabled to get the DMA to put the second converted value in
>>the buffer second position.>Thank you. it is obviously true>but unfortunatelly it does not solve the problem that only one sample is converted and>next conversion is not trigerred.I guess MemoryInc disabled can cause such problem, have you really tested it?2012-10-17 01:26 AM
Thank you all for the collaboration.
When I tried to test EOC flag in Main I increased ADC_SampleTime_4Cycles to ADC_SampleTime_384Cycles just to have time enough to get there. And then it started to work just because of this. 96+ cycles work correctly, 48 and less do not. My workaround is to decrease the Sample time, but I do not know the real reason. Maybe it is time to stury Sample time in reference manual again. to knik: I have had tested to change MemoryInc. I tried it again and played with it. If MemoryInc is disabled it the pointer is not incremented and the value alternates. With my original problem the ADC_ConvertedValue[0] was ''frozen'' since very first measurement.2012-10-17 02:05 AM
When I tried to test EOC flag in Main I increased ADC_SampleTime_4Cycles to ADC_SampleTime_384Cycles just to have time enough to get there.
And then it started to work just because of this.
I never had such an effect with F10x, F0 and F4 controllers. DMA worked regardless of ADC cycle time. Could be something L51 specific issue, possibly.
2012-10-17 07:21 AM
Sections 11.3.2 and 11.9 in the L151 reference manual discuss an ADC versus bus clock consideration that could be the source of the problem. You may have to set a delay between samples to achieve success.
Cheers, Hal