2021-11-30 11:00 PM
Hello
I m trying measure adc conversion time , I look datasheet , f_adc=37 Mhz(for fast channel)
with 12 bit resulation, 4.10 MSps , so ı use f_adc=32 Mhz(for fast channel) with 12 bit resulation, 3.54 MSps should be, but I m not measure 3.54 MSps,I measure 892 Ksps My measurement is as follows, when entering dma interrupt ,I toggle pin , then I set another pin At the end of the interrupt, I reset the pin again. the difference between the two times gives the adc conversion time.where is my fault project file and oscilloscope images are attached.
#include "main.h"
uint32_t cosa;
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
void adc2_config()
{
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_CLKP);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_ADC12);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC2, &ADC_InitStruct);
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE ;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE ;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE ;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
ADC_REG_InitStruct.DataTransferMode=LL_ADC_REG_DMA_TRANSFER_UNLIMITED;
LL_ADC_REG_Init(ADC2, &ADC_REG_InitStruct);
LL_ADC_SetOverSamplingScope(ADC2, LL_ADC_OVS_DISABLE);
// LL_ADC_REG_SetTriggerEdge(ADC2, LL_ADC_REG_TRIG_EXT_RISING);
ADC_CommonInitStruct.CommonClock =LL_ADC_CLOCK_ASYNC_DIV2;
ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC2), &ADC_CommonInitStruct);
LL_ADC_DisableDeepPowerDown(ADC2);
LL_ADC_EnableInternalRegulator(ADC2);
uint32_t wait_loop_index;
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while(wait_loop_index != 0)
{
wait_loop_index--;
}
LL_ADC_StartCalibration(ADC2,LL_ADC_CALIB_OFFSET , LL_ADC_SINGLE_ENDED);
while (LL_ADC_IsCalibrationOnGoing(ADC2) != 0);
LL_ADC_SetBoostMode(ADC2,LL_ADC_BOOST_MODE_50MHZ);
LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_5);
LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_5,LL_ADC_SAMPLINGTIME_2CYCLES_5 );
LL_ADC_SetChannelSingleDiff(ADC2, LL_ADC_CHANNEL_5, LL_ADC_SINGLE_ENDED);
LL_ADC_SetChannelPreSelection(ADC2, LL_ADC_CHANNEL_5);//PB1
LL_ADC_Enable(ADC2);
}
void adc2_dma_config()
{
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
LL_DMA_InitTypeDef DMA_InitStruct = {0};
NVIC_SetPriority(DMA2_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(DMA2_Stream1_IRQn);
DMA_InitStruct.Direction=LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
DMA_InitStruct.FIFOMode=LL_DMA_FIFOMODE_DISABLE;
DMA_InitStruct.FIFOThreshold=LL_DMA_FIFOTHRESHOLD_FULL;
DMA_InitStruct.MemBurst=LL_DMA_MBURST_SINGLE;
DMA_InitStruct.MemoryOrM2MDstAddress= (uint32_t)&cosa;
DMA_InitStruct.MemoryOrM2MDstDataSize=LL_DMA_MDATAALIGN_WORD;
DMA_InitStruct.MemoryOrM2MDstIncMode=LL_DMA_MEMORY_INCREMENT;
DMA_InitStruct.Mode=LL_DMA_MODE_CIRCULAR ;
DMA_InitStruct.NbData=1;
DMA_InitStruct.PeriphBurst=LL_DMA_PBURST_SINGLE;
DMA_InitStruct.PeriphOrM2MSrcAddress=(uint32_t)&ADC2->DR;
DMA_InitStruct.PeriphOrM2MSrcDataSize=LL_DMA_PDATAALIGN_WORD ;
DMA_InitStruct.PeriphOrM2MSrcIncMode=LL_DMA_PERIPH_NOINCREMENT;
DMA_InitStruct.Priority=LL_DMA_PRIORITY_VERYHIGH ;
DMA_InitStruct.PeriphRequest= LL_DMAMUX1_REQ_ADC2;
LL_DMA_Init(DMA2, LL_DMA_STREAM_1, & DMA_InitStruct);
LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_1);
LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_1);
LL_DMA_EnableIT_TE(DMA2, LL_DMA_STREAM_1);
}
void DMA2_Stream1_IRQHandler(void)
{
LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_0);// oscilloscope CH3
GPIOA->BSRR=0x00000001;//// oscilloscope CH4
if(LL_DMA_IsActiveFlag_TC1(DMA2))
{
LL_DMA_ClearFlag_TC1(DMA2);
LL_ADC_REG_StartConversion(ADC2);
GPIOA->BSRR=0x00010000;//// oscilloscope CH4
}
}
int main(void)
{
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),15, 0));
SystemClock_Config();
/
MX_GPIO_Init();
adc2_dma_config();
adc2_config();
while (LL_ADC_IsActiveFlag_ADRDY(ADC2) == 0)
{
}
LL_ADC_REG_StartConversion(ADC2);
while (1)
{
}
}
void SystemClock_Config(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_3)
{
}
LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
LL_RCC_HSI_Enable();
/* Wait till HSI is ready */
while(LL_RCC_HSI_IsReady() != 1)
{
}
LL_RCC_HSI_SetCalibTrimming(32);
LL_RCC_HSI_SetDivider(LL_RCC_HSI_DIV1);
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
LL_RCC_PLL1P_Enable();
LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL1_SetM(4);
LL_RCC_PLL1_SetN(30);
LL_RCC_PLL1_SetP(1);
LL_RCC_PLL1_SetQ(2);
LL_RCC_PLL1_SetR(2);
LL_RCC_PLL1_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL1_IsReady() != 1)
{
}
/* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
LL_Init1msTick(480000000);
LL_SetSystemCoreClock(480000000);
}
void PeriphCommonClock_Config(void)
{
LL_RCC_SetCLKPClockSource(LL_RCC_CLKP_CLKSOURCE_HSI);
}
static void MX_GPIO_Init(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
/**/
LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_0);
/**/
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
2021-11-30 11:21 PM
I m use stm32h723zg
2021-12-01 06:12 AM
Please don't PM me about threads.
You can't interrupt at the MHz rates, so instead of doing ONE sample, sample 10 or 100 and decimate the time to understand the sample rate. Use ping-pong buffers with the DMA HT/TC so you aren't working on active/changing data. Watch/manage cache coherency.
2021-12-01 06:53 AM
You cannot effectively measure the time for a single conversion. As I said in the other post you found, time 10000 conversions to reduce the overhead.
2021-12-01 09:39 PM
in other post, The person asking the question could not find a solution. so ı open new post because ı have same problem. I did what you said but the result did not change. time is still too long.
2021-12-01 09:42 PM
Can you explain this part-> "Use ping-pong buffers with the DMA HT/TC so you aren't working on active/changing data. Watch/manage cache coherency."
2022-09-01 08:35 PM
TDK, can you elaborate on "You cannot effectively measure the time for a single conversion"? Thanks.
-WQ
2022-09-01 08:37 PM
Tesla, can you elaborate on "You can't interrupt at the MHz rates?
-WQ
2022-09-01 09:29 PM
2022-09-01 09:59 PM
Well you'll saturate the MCU with a lot of context switching and all the burden you're carrying with the handlers, the HAL, and the callbacks.
The ceiling here is probably a lot lower than you think it is, and it scales very badly.