2023-09-21 03:15 PM - edited 2023-09-22 05:42 AM
Dear all,
I'm currently using the STM32MP157F-DK2 series, and I'm trying to use the ADC1 and ADC2 in dual regular simultaneous mode triggered by TIM2 out event. Also, I used one DMA stream (DMA2_stream0) to read the ADC values of the Common Data Register (ADC_CDR) as it is indicated in the MP157F reference manual:
This is how I'm starting the ADCs:
if(HAL_ADC_Start(&hadc2) != HAL_OK){
/* Start Error */
Error_Handler();
}
if (HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)adc_buff, 8) != HAL_OK)
{
/* Start Error */
Error_Handler();
}
if (HAL_TIM_Base_Start(&htim2) != HAL_OK)
{
Error_Handler();
}
Also, I have checked the ADC's registers, to make sure the configuration is correct. This is the configuration for the ADC1 and ADC2:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0}
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
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_DUALMODE_REGSIMULT;
multimode.DualModeData = ADC_DUALMODEDATAFORMAT_32_10_BITS;
multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_6;
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;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_13;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
static void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
/* USER CODE END ADC2_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Common config
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc2.Init.LowPowerAutoWait = DISABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DiscontinuousConvMode = DISABLE;
hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
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_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;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
/* USER CODE END ADC2_Init 2 */
}
In my understanding adcData_DMA = ADC_CDR so adcData_DMA bits[31:16] = ADC2 Data and adcData_DMA bits[15:0] = ADC1 data, in that order of ideas this is my callback:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
channels_adc[0] = adc_buff[0] & 0xFFF;
channels_adc[1] = adc_buff[1] & 0xFFF;
channels_adc[2] = adc_buff[0]>>16;
channels_adc[3] = adc_buff[1]>>16;
}
Where:
uint32_t adc_buff[2] = {0};
uint16_t channels_adc[4] = {0};
I have checked and the values are correct in the Common Data Register (I checked it with the debugger), but the are not in my buffer given by the DMAStream0 (adc_buff).
I don't know if I'm misunderstanding something or if I'm overlooking something. I greatly appreciate your collaboration.
Also I attached here the complete main.c file.
Best regards
2023-10-04 01:51 AM
Hello,
Do you mean channels_adc != adc_buff?
2023-10-04 11:43 AM
Thank you for the repply Ken.
adc_buff is the DMAbuffer, where it's supose to be the ADC1 data (bits[15:0]) and the ADC2 data (bits[31:16]).
The channels_adc[4] it's just the separate value (with masks) of each adc channel. The problem is that in DMAbuffer (adc_buff) it never have the correct values.
It's more clear?
2023-10-05 05:54 PM
Hi jutoroa,
The "DMAbuffer (adc_buff) never have the correct values", it means ADC1(channel 6, channel13), ADC2(channel 2, channel 6) never have the correct values or some channel can get the correct values.
I have encountered a situation where, in Dual ADC regular simultaneous mode, the ADC slave channel has a phase shift of one sample being ahead of ADC master. (I am not the only one seeing this issue.)
I'm not sure whether you have also encountered the same problem.
2023-10-17 09:01 AM
Hi Ken, thanks again for the repply. I still have the same issue. The problem is that one channel can't get the correct values into the DMABuffer. I have read the post, and I think it's correlated. ¿Do you know about a possible solution?