I am trying to make baremetal ADC driver for following development board STM32H723ZG Nucleo (144 pins).
- Reference manual: STM32H723 Reference Manual
- Datasheet STM32H7xx Nucleo Datasheet
To simplify, lets assume (for example) to use PA3. According to Datasheet, PA3 corresponds to Channel 15. In order to use ADC module and proper pins, I perform following actions:
- Enable Clk access to GPIOA
- Set PA3 as Analog Mode
- Enable Clk access to ADC1 module
- Set conversion mode of ADC1 to continuous
- Set sequence length to 1 (since only channel 15 is converted)
- Set ADC channel to be converted in SQR1 (channel 15)
- Disable deep powered mode by clearing DEEPPWD in Control Register
- Enable regulator voltage VREGEN in Control Register
- Wait for LDO to be supplied (LDORDY in ADC_ISR)
- Enable the ADC by setting ADEN in Control Register
- Start conversion with ADSTART in Control Register
Now the crazy thing is. All steps succeed. I can see the results in SFRs. But conversion is still not happening. Observing ADC_ISR bit ADRDY, it looks like ADC is not ready at all.
I dug through documentation forwards and backwards.
No errors triggered as well. Board is directly from the ST themselves.
Anyone has any helpful tips? :)
Thanks!
code:
#define ADC_1_CONV (0U << 4U)
#define ADC_ISR_LDO_RDY (1U << 12U)
#define PA3_ADC_CHN15 (15U << 6U)
void ADC_Init(void){
/**Configure the ADC pin**/
// Enable Clock Access to pins
RCC_SetAHB4_PeriphClock(RCC_AHB4ENR_GPIOAEN);
// Configure ADC pin to Analog mode
GPIO_SetPinMode(GPIOA,PA3_PIN,GPIO_ANALOG_MODE);
/* Configure the ADC module */
// Enable clock to ADC
RCC_SetAHB1_PeriphClock(RCC_AHB1ENR_ADC12EN);
// Set the conversion mode (continuous)
SET_BIT(ADC1->CFGR,ADC_CFGR_CONT);
// Set sequencer length
MODIFY_REG(ADC1->SQR1,ADC_SQR1_L,ADC_1_CONV);
// Set ADC channel
MODIFY_REG(ADC1->SQR1,ADC_SQR1_SQ1,PA3_ADC_CHN15);
//SET_BIT(ADC1->PCSEL_RES0,ADC_PCSEL_PCSEL_3);
//ADC_ISR_ADRDY
// Enable ADC module
CLEAR_BIT(ADC1->CR,ADC_CR_DEEPPWD);
SET_BIT(ADC1->CR,ADC_CR_ADVREGEN);
while (!(ADC1->ISR & ADC_ISR_LDO_RDY));
//SET_BIT(ADC1->ISR,ADC_ISR_ADRDY);
SET_BIT(ADC1->CR,ADC_CR_ADEN);
//while (!(ADC1->ISR & ADC_ISR_ADRDY));
for (int i = 0; i<10000; i++){};
// Start conversion
SET_BIT(ADC1->CR,ADC_CR_ADSTART);
}
Please note, helper functions like
GPIO_SetPinMode
and
RCC_SetAHB1_PeriphClock
work with 100% certainty :)
0b11
, to use the system clock (or some other divisor, depending on your clock frequency). The clock route through RCC is non-trivial, and you don't include any specific setup for that (other than enabling the ADC clock) so it may not be set up correctly by default. \$\endgroup\$