cancel
Showing results for 
Search instead for 
Did you mean: 

Bare Metal ADC on NUCLEO-H745ZI-Q

zirogravity
Associate II

Hello,

I am troubleshooting a similar problem as described in this post TM32H7 ADC Baremetal - Cannot get ADC module ready

I am using PF10 on ADC3 as it is already routed to the CN10 header. Intentionally ignoring CMSIS header/defines in the spirit of learning. Using the default RCC /64MHz HSI / clock and have basic uart functionality on usart3. Using CM4 and ignoring CM7.

Initializing as follows:

//Enable clock access to GPIOF
RCC->AHB4ENR |=GPIOFEN;

//Set PF10 mode to analog
//The reset state for the pins is analog mode
//GPIOF->MODER |=(1U<<20);
//GPIOF->MODER |=(1U<<21);

//Enable clock access to ADC
RCC->AHB4ENR |=ADC3EN;

//Set ADC Kernel Clock Source to Peripheral Clock
RCC->D3CCIPR &=~(1U<<16);
RCC->D3CCIPR |= (1U<<17);

//Reset the ADC peripheral
RCC->AHB4RSTR |= (1U<<24);
RCC->AHB4RSTR &=~(1U<<24);

//DISABLE THE ADC BEFORE CONFIGURATION
ADC3->CR &=~ADEN;
while(ADC3->CR & ADEN){};

//ADC channel pre-selection register
ADC3->PCSEL  |=(1U<<6);

//Set ADC Continous Conversion Mode
ADC3->CFGR |=(1U<<13);

//ADC Channel Sequence
//Channel 6 of ADC3 so we need ADC_SQR1: SQ[4:0]=6 =0b110
//Only one channel ADC_SQR1:  L[3:0]=0 (length 1)
ADC3->SQR1 &= ~(1U<<0);
ADC3->SQR1 |=  (1U<<7);
ADC3->SQR1 |=  (1U<<8);

//Set ADC Clock Mode
//00: CK_ADCx (x=1 to 23) (Asynchronous clock mode), generated at product level (refer to
//Section Reset and Clock Control (RCC))
//01: adc_sclk/1 (Synchronous clock mode).
//10: adc_sclk/2 (Synchronous clock mode)
//11: adc_sclk/4 (Synchronous clock mode)
ADC3_COMMON->CCR |=((1U<<16)|(1U<<17));

//Clear the Deep Power Down Bit
ADC3->CR &=~DEEPPWD;

//Enable the ADC VREG
ADC3->CR |= ADVREGEN;

//Wait for ADC LDO Ready Flag
while(!(ADC3->ISR & LDORDY));

//1. Clear the ADRDY bit in the ADC_ISR register by writing ‘1’
ADC3->ISR |=ISR_ADRDY;

//2. Set ADEN=1.
ADC3->CR |= ADEN;

//3. Wait until ADRDY=1 (ADRDY is set after the ADC startup time). 
while(!(ADC3->ISR & ISR_ADRDY)){};

//4. Clear the ADRDY bit in the ADC_ISR register by writing ‘1’ (optional).
//ADC3->ISR |=ISR_ADRDY;

 It appears that I get a single ADC reading on "reset" but nothing after that. I can GND or apply 3.3V on PF10 and report an ADC count value via uart.

Screenshot from 2024-11-26 18-02-05.png

My adc read function and from what I can tell EOC never gets set/reset after each read.

uint32_t adc_read(void){

	//RM0399 Rev 4 page 1034
	//Wait for conversion completion
	 while(!(ADC3->ISR & ISR_EOC)){};

	 //Wait for sequence completion
	 //while(!(ADC3->ISR & ISR_EOS));

	//Read converted results
	return (ADC3->DR);
}

I have tried various insertions of delays in the form of:

for(int i=0; i<10000;i++);

 in various section of the code per the RM but that does not seem to be it. My overall main() is:

uint32_t adc3_ch6_count;

int main(void){

	usart3_tx_init();

	pf10_adc_init();

	start_conversion(); //Start ADC Conversion ADC3->CR |=  ADSTART;
}

	while(1){

		//for (int i=0;i<10000;i++);
		adc3_ch6_count =adc_read();
		printf("\nADC3_CH6 Count: %lu\r", adc3_ch6_count);
		for(int i=0; i<10000;i++);

	}
}

 

3 REPLIES 3
zirogravity
Associate II

Hi,

I am just noticing that the LDORDY bit field is not shown in the SFR debug view for STM32CubeIDE. Bit 12 is being set correctly. This should be OK I suppose and unrelated to why my code does not get past a reset/single read?stm32LDORDYMarkUp.png

stm32LDORDYMarkUp2.png

krotti42
Associate III

Hello @zirogravity !

 

NOTE

You have written, you use the default RCC/PWR setup. So the peripheral kernel clock is 64MHz.

The maximum allowed frequency for the ADC's is 40MHz (VOS3), 60MHz (VOS2) and 160MHz (VOS1 and VOS0).  Have you changed the voltage scaling (VOS) to VOS1 with the power controller (PWR)? The default is VOS3.

 

 

 

ADC maximum allowed frequencyADC maximum allowed frequency

 

 

 

Hi @krotti42 ,

Thank you for this insight. I will have a look today, make some changes, and report back. Perhaps I misunderstood but I thought when CKMODE[1:0] is set to 01 or 11 the prescaler would be either 2 or 4 which gets further divided by 2 according to Figure 142 ADC Clock Scheme diagram. The information shared is very helpful and I will test out. I have not changed or set VOS at all.


Screenshot from 2024-11-28 08-02-52.png