2020-11-27 04:53 AM
For a given application I am trying to control the main loop speed thorugh the ADC sampling rate. My objective is targeting a fast embedded control application so I plan to go in the 100kHz-10MHz range (yes, I am aware of the STM32H7 limitations for GPIO manipulation at high loop frequency). Relevant parts of my main.c are:
MX_GPIO_Init();
MX_ADC1_Init();
MX_ADC2_Init();
HAL_ADC_Start(&hadc1);
HAL_ADC_Start(&hadc2);
while (1)
{
g_MeasurementNumber++;
GPIOE->BSRR = (1<<1); //set to high
while((ADC1->ISR == (0<<2))){ //wait for EOC
};
g_ADCValue0 = ADC1 ->DR;
while((ADC2->ISR == (0<<2))){ //wait for EOC
};
g_ADCValue = ADC2 ->DR;
GPIOE->BSRR = (1<<17); //set to low 1+16
}
There, GPIOE registers are manipulated for generating a signal I can easily measure in the oscilloscope. ADC1 and ADC2 are configured for continuous acquisition with data override, and values in DR registers are coherent with the applied voltage.
The thing is that the while loop is done at around 3 MHz without any effect of the ADC clock prescaler or sampling period selected. What I am expecting is that, when one of the channels is set to a different sampling frequency (e.g. below: ADC2 set to ADC_CLOCK_ASYNC_DIV256 and ADC_SAMPLETIME_810CYCLES_5), the complete main loop cycle time is affected.
I have tried wih EOC flag ISR(2), EOS flag ISR(3) -SW cleared afterwards-, and countless configurations, including using a single ADC and varying bit depth, so there is something I am doing wrong. I checked in SMPR1 register that sampling information is correctly sent to the ADC registers. I am incrrectly interpreting (or accessing) EOC flag?
static void MX_ADC1_Init(void)
{
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6;
hadc1.Init.Resolution = ADC_RESOLUTION_16B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* @brief ADC2 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC2_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** Common config
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV256;
hadc2.Init.Resolution = ADC_RESOLUTION_16B;
hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.ContinuousConvMode = ENABLE;
hadc2.Init.NbrOfConversion = 1;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc2.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
Solved! Go to Solution.
2020-11-27 05:47 AM
OK... just needed to review my bitwise comparison skills:
not
(ADC1->ISR == (0<<2))
but
((ADC1->ISR & (1<<2))==0)
or
((ADC1->ISR & ADC_ISR_EOC)==0)
2020-11-27 05:47 AM
OK... just needed to review my bitwise comparison skills:
not
(ADC1->ISR == (0<<2))
but
((ADC1->ISR & (1<<2))==0)
or
((ADC1->ISR & ADC_ISR_EOC)==0)