STM32MP157F-DK2 Dual ADC with DMA
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-09-21 3:15 PM - edited ‎2023-09-22 5: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-04 1:51 AM
Hello,
Do you mean channels_adc != adc_buff?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-05 5: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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-17 9: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?
