2024-01-29 09:04 PM
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...)
Solved! Go to Solution.
2024-01-30 07:31 AM
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;
}
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.
2024-01-30 07:31 AM
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;
}
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.
2024-01-30 08:47 AM
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?
2024-02-07 05:57 AM
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);
}
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.