Skip to main content
Explorer
January 30, 2024
Solved

STM32H723ZGT6 ADC stuck after first sample

  • January 30, 2024
  • 2 replies
  • 1986 views

I'm trying, unsuccessfully, to get a simplest single-channel single-ended polling-the-ADC example going on the nucleo h723 eval board.

At first I started bare-metal in assembler from the datasheet, but couldn't get the second ADC sample to fire no matter what register gymnastics I did (the first ADSTART puts some bits in the DR, I figure that did something to the analog input).

Then, figuring I'm still not setting up clocks right or something, I reverted to STM32CubeIDE and followed various HAL tutorials such as this one; same outcome.

https://www.youtube.com/watch?v=6uiO68pdjZA

This particular ADC seems more involved than the simple ones usually covered in tutorials. Can anyone point me to an example of repeated single-shot acquisition with polling or interrupts that actually works on the 723ZGT6 part?

(Bonus points if it can actually run at the claimed 3.5 MS/s...)

    This topic has been closed for replies.
    Best answer by Hl_st

    Hello,

    there is one simple example of using ADC. This code initialize ADC with input as PA0 and than conversing this input in infinite loop :

    /* Enable GPIOA peripheral clock */
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN;

    /* Peripheral ADC clock enable */
    RCC->APBENR2 |= RCC_APBENR2_ADCEN;

    /* Enable ADC internal voltage regulator */
    ADC1->CR |= ADC_CR_ADVREGEN;
    int i = 160000;
    while(i > 0) i--;

    /* Configure CHNNEL_0 (PA0) as ADC input */
    ADC1->CHSELR |= ADC_CHSELR_CHSEL0;

    /* ADC calibration */
    ADC1->CR |= ADC_CR_ADCAL;
    while ((ADC1->CR & ADC_CR_ADCAL) == (ADC_CR_ADCAL));

    /* ADC Enable */
    ADC1->CR |= ADC_CR_ADEN;

    /* Infinite loop */
    while (1)
    {
    /* Start conversion */
    MODIFY_REG(ADC1->CR, (ADC_CR_ADSTP | ADC_CR_ADSTART), ADC_CR_ADSTART);
    /* Wait for end of conversion */
    while ((ADC1->ISR & ADC_ISR_EOC) != ADC_ISR_EOC);
    /* Stop conversion */
    MODIFY_REG(ADC1->CR, (ADC_CR_ADSTP | ADC_CR_ADSTART), ADC_CR_ADSTP);

    /* Clear flag end of conversion */
    ADC1->ISR = ADC_ISR_EOC;
    /* Read converted data */
    int result = ADC1->DR;
    }

    2 replies

    Hl_stAnswer
    ST Employee
    January 30, 2024

    Hello,

    there is one simple example of using ADC. This code initialize ADC with input as PA0 and than conversing this input in infinite loop :

    /* Enable GPIOA peripheral clock */
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN;

    /* Peripheral ADC clock enable */
    RCC->APBENR2 |= RCC_APBENR2_ADCEN;

    /* Enable ADC internal voltage regulator */
    ADC1->CR |= ADC_CR_ADVREGEN;
    int i = 160000;
    while(i > 0) i--;

    /* Configure CHNNEL_0 (PA0) as ADC input */
    ADC1->CHSELR |= ADC_CHSELR_CHSEL0;

    /* ADC calibration */
    ADC1->CR |= ADC_CR_ADCAL;
    while ((ADC1->CR & ADC_CR_ADCAL) == (ADC_CR_ADCAL));

    /* ADC Enable */
    ADC1->CR |= ADC_CR_ADEN;

    /* Infinite loop */
    while (1)
    {
    /* Start conversion */
    MODIFY_REG(ADC1->CR, (ADC_CR_ADSTP | ADC_CR_ADSTART), ADC_CR_ADSTART);
    /* Wait for end of conversion */
    while ((ADC1->ISR & ADC_ISR_EOC) != ADC_ISR_EOC);
    /* Stop conversion */
    MODIFY_REG(ADC1->CR, (ADC_CR_ADSTP | ADC_CR_ADSTART), ADC_CR_ADSTP);

    /* Clear flag end of conversion */
    ADC1->ISR = ADC_ISR_EOC;
    /* Read converted data */
    int result = ADC1->DR;
    }

    n719zAuthor
    Explorer
    January 30, 2024

    Aaand there it is, the key... Thank you!

     

    So the missing piece, then, is that one must STOP the conversion before starting the next one. The TRM wording implies that simply reading the DR clears the EOC bit, which obviously doesn't reset the state machine to a truly ready state despite the ready bit reading as one. We can debate this point, but shouldn't the HAL already do this for me the dumb user in HAL_ADC_GetValue(), and/or HAL_ADC_Start() for that matter, if single-conversion mode is set?

    ST Employee
    February 7, 2024

    The conversion don´t have to be stopped if the conversion was correctly done. You are right that if you read DR, the EOC is cleared by hardware so it is not necessary to clear it by software so it should also works if you try HAL library:

    /* Calibrate ADC */
    HAL_ADCEx_Calibration_Start(&hadc1);


    while (1)
    {
    /* Start ADC conversion */
    HAL_ADC_Start(&hadc1);

    /* Wait for end of conversion */
    HAL_ADC_PollForConversion(&hadc1, 100);

    /* Read converted data */
    int result = HAL_ADC_GetValue(&hadc1);
    }