cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 - ADC synchronuous clock mode wrong

vincenthamp9
Associate III
Posted on November 04, 2015 at 10:46

Hello there

I've a question regarding the ADC conversion time on the STM32L476. According to the datasheet the fastest possible conversion time running at 80MHz is 187ns. Does this also count for the continuous conversion mode + DMA?

From my observations I'd say there is some kind of overhead involved in this particular conversion mode. Currently I've a motor PWM running at 50µs and start a current measurement of 128x samples each timer trigger. At 80MHz 128x samples should be around ~24µs or ''half a PWM period''. Well... thats not the case...

The actual motor current looks like that:

http://i.pictr.com/apm9k86ibj.png

Whereas the measured 128x samples look like that:

http://i.pictr.com/8jios97q60.png

As you can see those 128x samples represent almost a whole PWM period although they should only be ~24µs in length... How is that possible?

tia
6 REPLIES 6
raptorhal2
Lead
Posted on November 04, 2015 at 19:17

Which ADC & channel?

What sampling cycles ?

Cheers, Hal

Posted on November 04, 2015 at 19:59

I don't see any code.

May be you have a prescaler, or the part isn't clocking at the rate you think it is.

I'd look at the internal clocks via the MCO, and for things like the DISCO board be very careful about the HSE/BYPASS settings.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
vincenthamp9
Associate III
Posted on November 05, 2015 at 10:41

HAL Lib initialization:

static HAL_StatusTypeDef adc_i_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_ChannelConfTypeDef sConfig;
uint32_t tickstart;
/* DMA interrupt init */
HAL_NVIC_SetPriority(ADC_I_DMA_IRQn, IRQ_PRIO_DMA_ADC_I, 0);
HAL_NVIC_EnableIRQ(ADC_I_DMA_IRQn);
/* ADC1 GPIO Configuration
* PA3 ------> ADC1_IN8
*/
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_adc_i.Instance = ADC_I_DMA_CHANNEL;
hdma_adc_i.Init.Request = DMA_REQUEST_0;
hdma_adc_i.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc_i.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc_i.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc_i.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc_i.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc_i.Init.Mode = DMA_NORMAL;
hdma_adc_i.Init.Priority = DMA_PRIO_ADC_I;
HAL_DMA_Init(&hdma_adc_i);
__HAL_LINKDMA(&hadc_i,DMA_Handle,hdma_adc_i);
/* Common config ADC_I */
hadc_i.Instance = ADC_I;
hadc_i.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc_i.Init.Resolution = ADC_RESOLUTION_12B;
hadc_i.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc_i.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc_i.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc_i.Init.LowPowerAutoWait = DISABLE;
hadc_i.Init.ContinuousConvMode = ENABLE;
hadc_i.Init.NbrOfConversion = 1;
hadc_i.Init.DiscontinuousConvMode = DISABLE;
hadc_i.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_TRGO2; // Triggered by TIM_MOTOR
hadc_i.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc_i.Init.DMAContinuousRequests = DISABLE;
hadc_i.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc_i.Init.OversamplingMode = DISABLE;
if(HAL_ADC_Init(&hadc_i) != HAL_OK)
return HAL_ERROR;
/* Configure Regular Channel */
sConfig.Channel = ADC_CH_IMOTOR;
sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLE_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.Rank = 1;
HAL_ADC_ConfigChannel(&hadc_i, &sConfig);
/* Calibrate ADC_I */
if(HAL_ADCEx_Calibration_Start(&hadc_i, ADC_SINGLE_ENDED) != HAL_OK)
return HAL_ERROR;
/* Enable ADC_I DMA and ADC_I */
ADC_I->CFGR |= ADC_CFGR_DMAEN;
ADC_I->CR |= ADC_CR_ADEN;
/* Wait for ADC_I effectively enabled */
tickstart = HAL_GetTick();
while(!(ADC_I->ISR & ADC_ISR_ADRDY))
{
ADC_I->CR |= ADC_CR_ADEN;
if((HAL_GetTick()-tickstart) > ADC_ENABLE_TIMEOUT)
return HAL_ERROR;
}
/* Enable ADC_I DMA
* Set DMA data transfer direction to read from peripheral
*/
ADC_I_DMA_CHANNEL->CCR &= ~DMA_CCR_DIR;
/* Configure DMA Channel data length */
ADC_I_DMA_CHANNEL->CNDTR = (uint32_t)SIZE_ADC_I_BUFFER;
/* Configure DMA Channel source address */
ADC_I_DMA_CHANNEL->CPAR = (uint32_t)&ADC_I->DR;
/* Configure DMA Channel destination address */
ADC_I_DMA_CHANNEL->CMAR = (uint32_t)&t_adc.t_imot.buf1;
/* Enable the transfer complete interrupt, transfer error interrupt and channel */
ADC_I_DMA_CHANNEL->CCR |= DMA_CCR_TCIE | DMA_CCR_TEIE | DMA_CCR_EN;
/* Start ADC_I */
ADC_I->CR |= ADC_CR_ADSTART;
return HAL_OK;
}

In short: ADC1, Channel 8 (OPAMP output), no prescaler, 2.5 cycles /edit Well well... I just figured out that the STM32L4 has only one ADC clock. I've the two other ADCs configured with different prescalers. So the question now is... how do I determine the actual ADC clock? I just tried reading the common CCR register which holds the PRESC bits and Eclipse keeps telling me it's zero. What the hell?
vincenthamp9
Associate III
Posted on November 05, 2015 at 13:36

I'm sorry for the double post, but the new ADC clock scheme is driving me crazy.

So I just changed my ADC clock mode from asynchronous to synchronous mode, so that the ADC is driven by HCLK which is 80MHz is my case. The prescaler is set to 1 (CKMODE bits = 0b01).

80MHz * (2.5 + 12.5 cycles conversion time) * 128 samples = 24µs

But this isn't the case. 128 samples still take 48µs, which is twice as long.

Now I know that the AHB prescaler isn't allowed any other values than 1 if this clock mode is used, but I checked that twice now and that damn prescaler is 1 and nothing else. So why the hell am I still sampling with 380ns and not the actual ~180ns which are promised in the data sheet?

/edit

found it...

[DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/%5bBug%5d%20CubeMX%2c%20STM32L4%2c%20ADC%20synchronuous%20clock%20settings&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E3A95BA69146A17C2E80209ADC21&TopicsView=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/AllItems.aspx&currentviews=1]''bug''-report
raptorhal2
Lead
Posted on November 05, 2015 at 22:42

One factor - you are sampling a slow channel and assuming fast channel performance.

Cheers, Hal

vincenthamp9
Associate III
Posted on November 07, 2015 at 16:55

Well... thanks!

I haven't even thought about that. I got confused with all the OPAMP input/output stuff.

But the injected channel stuff still solved the issue for me.