cancel
Showing results for 
Search instead for 
Did you mean: 

H7: ADC1 & ADC2 Dual Regular Simultaneous Mode Mirroring - Slave Not Responding

Pandian
Associate II

Hi everyone,

I am working on STM32H723 (H7 series) using HAL, and I am facing an issue with ADC1 + ADC2 dual regular simultaneous mode.

Configuration Details

  • MCU: STM32H723

  • HAL based project

  • ADC1 = Master

  • ADC2 = Slave

  • Mode: ADC_DUALMODE_REGSIMULT

  • DualModeData: ADC_DUALMODEDATAFORMAT_32_10_BITS

  • Resolution: 12-bit

  • Scan mode: Disabled

  • Continuous mode: Disabled

  • Trigger source: TIM2_TRGO (rising edge)

  • DMA: Circular mode

  • ADC3 runs independently (also TIM2 triggered) and works perfectly

Dual mode started using:

HAL_ADCEx_MultiModeStart_DMA(&hadc1,
(uint32_t*)g_adc12_packed_buffer,
TP_DMA_BUFFER_SIZE);
 

Buffer unpacking:

 

 
uint32_t packed = g_adc12_packed_buffer[i];
uint16_t adc1_raw = packed & 0xFFFF;
uint16_t adc2_raw = packed >> 16;
 

Observed Behaviour

  1. When I apply voltage to ADC1 input:

    • Both ADC1 and ADC2 values change

    • Both show identical values (mirrored)

  2. When I apply voltage to ADC2 input:

    • No change in readings

    • ADC2 does not respond

  3. When inputs are floating (level shifted mid-scale ~2048 expected):

    • Both ADC1 and ADC2 periodically read 0

    • Then both read ~2048

    • Alternates in blocks

    • ADC3 continues working correctly

  4. But when i configure an all adc independently it works correctly, when i configure an dual regular simultaneous mode it behaves like this.

//MCU : STM32 H723VET6
//HAL PROJECT
//SYS clk : 550MHZ
//ADC Clk : 36MHZ

//-----------------adc1 configurations master----------------------
void ThreePhase_ADC1_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};
    ADC_MultiModeTypeDef multimode = {0};

    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV2;
    hadc1.Init.Resolution            = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode          = ADC_SCAN_DISABLE;
    hadc1.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
    hadc1.Init.LowPowerAutoWait      = DISABLE;
    hadc1.Init.ContinuousConvMode    = DISABLE;
    hadc1.Init.NbrOfConversion       = 1;
    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_OVERWRITTEN;
    hadc1.Init.LeftBitShift          = ADC_LEFTBITSHIFT_NONE;
    hadc1.Init.OversamplingMode      = DISABLE;

    if (HAL_ADC_Init(&hadc1) != HAL_OK)
        Error_Handler();

    /* Regular simultaneous mode */
    multimode.Mode = ADC_DUALMODE_REGSIMULT;
//    multimode.Mode = ADC_MODE_INDEPENDENT;
    multimode.DualModeData = ADC_DUALMODEDATAFORMAT_32_10_BITS;
    multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;

    if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
        Error_Handler();

    /* Channel 16 (PA0) */
    sConfig.Channel      = ADC_CHANNEL_16;
    sConfig.Rank         = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_32CYCLES_5;
    sConfig.SingleDiff   = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
        Error_Handler();

    HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
}

//----------------adc2 configurations slave------------------------------------

void ThreePhase_ADC2_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    hadc2.Instance = ADC2;
    hadc2.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV2;
    hadc2.Init.Resolution            = ADC_RESOLUTION_12B;
    hadc2.Init.ScanConvMode          = ADC_SCAN_DISABLE;
    hadc2.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
    hadc2.Init.LowPowerAutoWait      = DISABLE;
    hadc2.Init.ContinuousConvMode    = DISABLE;
    hadc2.Init.NbrOfConversion       = 1;
    hadc2.Init.DiscontinuousConvMode = DISABLE;

    /* NO external trigger — slave follows master */
    hadc2.Init.ExternalTrigConv      = ADC_SOFTWARE_START;
    hadc2.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;

    hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
    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();

    /* Channel 3 (PA6) */
    sConfig.Channel      = ADC_CHANNEL_3;
    sConfig.Rank         = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_32CYCLES_5;
    sConfig.SingleDiff   = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;

    if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
        Error_Handler();

    HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
}
//-----------------------adc3 configurations independent-----------------------
void ThreePhase_ADC3_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    hadc3.Instance = ADC3;
    hadc3.Init.ClockPrescaler        = ADC_CLOCK_ASYNC_DIV2;
    hadc3.Init.Resolution            = ADC_RESOLUTION_12B;
    hadc3.Init.ScanConvMode          = ADC_SCAN_DISABLE;
    hadc3.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
    hadc3.Init.LowPowerAutoWait      = DISABLE;
    hadc3.Init.ContinuousConvMode    = DISABLE;
    hadc3.Init.NbrOfConversion       = 1;
    hadc3.Init.DiscontinuousConvMode = DISABLE;
    hadc3.Init.ExternalTrigConv      = ADC_EXTERNALTRIG_T2_TRGO;
    hadc3.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_RISING;
    hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
    hadc3.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;
    hadc3.Init.LeftBitShift          = ADC_LEFTBITSHIFT_NONE;
    hadc3.Init.OversamplingMode      = DISABLE;

    if (HAL_ADC_Init(&hadc3) != HAL_OK)
        Error_Handler();

    /* Channel 10 (PC0) */
    sConfig.Channel      = ADC_CHANNEL_10;
    sConfig.Rank         = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC3_SAMPLETIME_47CYCLES_5;
    sConfig.SingleDiff   = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;

    if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
        Error_Handler();

    HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
}

//-------------------Bufffer initialisation------------------------------------
#define TP_DMA_BUFFER_SIZE   2048U

volatile uint32_t g_adc12_packed_buffer[TP_DMA_BUFFER_SIZE] __attribute__((aligned(32)));

volatile uint16_t g_adc1_buffer[TP_DMA_BUFFER_SIZE] __attribute__((aligned(32)));
volatile uint16_t g_adc2_buffer[TP_DMA_BUFFER_SIZE] __attribute__((aligned(32)));
volatile uint16_t g_adc3_buffer[TP_DMA_BUFFER_SIZE] __attribute__((aligned(32)));


//--------------------Callbacks Half & Full callback-----------------------------
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
{
    if (adc_mode == ADC_MODE_THREEPHASE)
    {
        if (hadc == &hadc1)
        {
        	/* Invalidate first half of packed buffer */
			SCB_InvalidateDCache_by_Addr(
				(uint32_t*)g_adc12_packed_buffer,
				(TP_DMA_BUFFER_SIZE / 2) * sizeof(uint32_t)
			);

			/* Unpack first half */
			for (uint32_t i = 0; i < TP_DMA_BUFFER_SIZE / 2; i++)
			{
				uint32_t packed = g_adc12_packed_buffer[i];

				g_adc1_buffer[i] = (uint16_t)(packed & 0xFFFF);
				g_adc2_buffer[i] = (uint16_t)(packed >> 16);
			}
        }
        else if (hadc == &hadc2)
        {
            SCB_InvalidateDCache_by_Addr(
                (uint32_t*)g_adc2_buffer,
                (TP_DMA_BUFFER_SIZE / 2) * sizeof(uint16_t)
            );
        }
        else if (hadc == &hadc3)
        {
            SCB_InvalidateDCache_by_Addr(
                (uint32_t*)g_adc3_buffer,
                (TP_DMA_BUFFER_SIZE / 2) * sizeof(uint16_t)
            );
        }
    }
    else
    {
        if (hadc == &hadc3)
        {
            SCB_InvalidateDCache_by_Addr(
                (uint32_t*)adc3Buffer,
                (ADC_BUFFER_SIZE / 2) * sizeof(uint16_t)
            );

            dma3_half_ready = 1;
        }
    }
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    /* ================= STREAMING ================= */
    if (adc_mode == ADC_MODE_STREAMING)
    {
        if (hadc == &hadc3)
        {
            SCB_InvalidateDCache_by_Addr(
                (uint32_t*)&adc3Buffer[ADC_BUFFER_SIZE / 2],
                (ADC_BUFFER_SIZE / 2) * sizeof(uint16_t)
            );

            dma3_full_ready = 1;
        }
    }

    /* ================= FREQ ================= */
    else if (adc_mode == ADC_MODE_FREQ)
    {
        if (hadc == &hadc3)
            dma3_full_ready = 1;
    }

    /* ================= LCR ================= */
    else if (adc_mode == ADC_MODE_LCR)
    {
        if (hadc == &hadc1)
            adc_done = true;

        if (hadc == &hadc3)
            dma3_full_ready = 1;
    }

    /* ================= THREE PHASE ================= */
    else if (adc_mode == ADC_MODE_THREEPHASE)
    {
        if (hadc == &hadc1)
        {
        	SCB_InvalidateDCache_by_Addr(
        	    (uint32_t*)&g_adc12_packed_buffer[TP_DMA_BUFFER_SIZE / 2],
        	    (TP_DMA_BUFFER_SIZE / 2) * sizeof(uint32_t)
        	);
	        /* Unpack */
        	for (uint32_t i = TP_DMA_BUFFER_SIZE / 2;
        	     i < TP_DMA_BUFFER_SIZE;
        	     i++)
        	{
        	    uint32_t packed = g_adc12_packed_buffer[i];

        	    g_adc1_buffer[i] = (uint16_t)(packed & 0xFFFF);
        	    g_adc2_buffer[i] = (uint16_t)(packed >> 16);
        	}
        }
//        else if (hadc == &hadc2)
//        {
//            SCB_InvalidateDCache_by_Addr(
//                (uint32_t*)&g_adc2_buffer[TP_DMA_BUFFER_SIZE / 2],
//                (TP_DMA_BUFFER_SIZE / 2) * sizeof(uint16_t)
//            );
//        }
        else if (hadc == &hadc3)
        {
            SCB_InvalidateDCache_by_Addr(
                (uint32_t*)&g_adc3_buffer[TP_DMA_BUFFER_SIZE / 2],
                (TP_DMA_BUFFER_SIZE / 2) * sizeof(uint16_t)
            );

            g_buffer_timestamp_us = __HAL_TIM_GET_COUNTER(&htim5);
            g_buffer_ready = 1;
        }

        if (g_test_scenario == SCENARIO_VOLTAGE_ONLY)
        {
            g_voltage_ready = 1;
        }
        else if (g_test_scenario == SCENARIO_CURRENT_ONLY)
        {
            g_current_ready = 1;
        }
        else
        {
            /* alternating mode */
            if (g_current_mode == MODE_VOLTAGE)
                g_voltage_ready = 1;
            else
                g_current_ready = 1;
        }
    }
}
//-----------------------------Callbacks end----------------------------

 

1 REPLY 1
Saket_Om
ST Employee

Hello @Pandian 

ADC configuration is correct ; could you please add precisions on system configuration?

ADC kernel clock frequency? (STM32H723 ADC freq max is 50MHz with boost=0b11)

The issue could be related also to impedance at board level: please refer to datasheet parameter "Rain".

For debug, could be interesting to increase sampling time from 32.5 to 810.5 ADC clock cycles.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om