cancel
Showing results for 
Search instead for 
Did you mean: 

ADC output ranging about 2000 up to 4095

APTT
Associate II

I'm running an STM32L452RCTX uC, and I'm trying to implement a 2.5Vref+ ADC.

Things weren't looking quite right on the pins I intend to implement, so for now I'm driving a floating TP with a power supply so I can directly test input vs output.

When driving the pin to ground, the output is around 2000 (I've seen it in the 198X through 200X range).

When increasing the voltage, I reach the full 4095 at 2.35V, which I feel is reasonably close to my measured 2.482 reference for my application.

I've scoured everywhere I can think of, and I can't seem to find any information on why this might happen.  The behavior is almost as if the Vref- is somewhere near -2.5V, but I have that pin (confirmed through measurement) tied to ground.

 

As for circuitry, I have 3.3V running through a 470 ohm resistor to the top of a 2.5V zener (LM4040), across two caps to ground (2.2uF and 0.1uF), and through a series 0 ohm resistor into the Vref+ pin.  The Vref- pin is soldered directly to the ground plane.  The test point I am driving is about 3mm from the pin of the uC.

 

And the programming, using the HAL drivers:

 

 

APTT_0-1701355234848.png

 

 

 

//Additional initializations beyond HAL implementation
	HAL_ADC_Stop(&hadc1);
  	HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);

//Battery checker, in main loop
	if(check_adc && ((hadc1.State & HAL_ADC_STATE_READY) == HAL_ADC_STATE_READY))
		{
		//Configure ADC for conversion
		adc_channel = TP_ADC;
		sConfig.Channel = adc_channel;
		sConfig.Rank = 1;
		if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
			{
			Error_Handler();
			}
		if (HAL_ADC_Start(&hadc1) != HAL_OK)
			{
			Error_Handler();
			}
		if (HAL_ADC_PollForConversion(&hadc1, 100) != HAL_OK)
			{
			Error_Handler();
			}
		if (HAL_ADC_Stop(&hadc1) != HAL_OK)
			{
			Error_Handler();
			}
		if (HAL_ADC_Start(&hadc1) != HAL_OK)
			{
			Error_Handler();
			}
		if (HAL_ADC_PollForConversion(&hadc1, 100) != HAL_OK)
			{
			Error_Handler();
			}
		uint16_t temmp = hadc1.Instance->DR;
		HAL_ADC_Stop(&hadc1);
		check_adc = NO;
		adc_check_timer = ADC_CHECK_TIME;
		}

 

 

 

Registers while device is paused, currently a floating pin:

APTT_0-1701354855868.png

APTT_1-1701354898880.png

 

And measured results of the DR register:
Pin grounded: 0x7C0

Pin floating: 0x8E2

Pin 3.324V: 0xFBF

 

16 REPLIES 16

The ADC channel could be in differential mode. Are you missing sConfig.SingleDiff = ADC_SINGLE_ENDED? Or other members of sConfig? That part of your code isn't shown.

Perhaps run a known working example on your board, only changing the channel number to what you're testing:

https://github.com/STMicroelectronics/STM32CubeL4/blob/master/Projects/NUCLEO-L452RE/Examples/ADC/ADC_RegularConversion_Polling/Src/main.c

If you feel a post has answered your question, please click "Accept as Solution".

> ADC reading of internal VREFINT returns 0x5a +/- 2

That sounds very wrong.

> My VDDA pin is the same pin as VREF+, and is soldered directly to the ground plane.

You surely meant VSSA and VREF-.

> The ADC channel could be in differential mode.

Sounds much like so.

Read out and check/post content of ADC registers.

JW

raptorhal2
Lead

Are you using a 2 prong wall wart to supply the signal? Strange results can happen if the negative output is not well grounded.

LCE
Principal

>> My VDDA pin is the same pin as VREF+, and is soldered directly to the ground plane.

> You surely meant VSSA and VREF-.

Hopefully, almost got a heart attack when I read that! :D

> The ADC channel could be in differential mode.

+1

APTT
Associate II

@TDK:

This is single-ended, and configured as such.  I did post a screenshot of the ioc setup, I'll amend my original post with this information.

I'll give it a shot, couldn't hurt.  I *can* tell you I've compared my code to several of the sample projects for ADC, as well as comparing with code written by my boss on a different project, and the code looks correct.

 

@waclawek.jan:

I agree, but it is what I see on ADC_CHANNEL_0 DR

Yes, you are correct.  My brain likes to flip opposites.  On another note, I don't think I'll ever understand how to properly use pointers without looking it up first.

I agree something seems fishy here, and that would be a nice solution, but alas, it is very much configured in single-ended mode.

I'll post a screenshot (or a few) of my register readouts for ADC1 and ADC123_Common in the original post.

 

@raptorhal2:

I am using a BK Precision 1735A 30V/3A DC power supply, which itself is plugged into a 6-outlet extension strip to the wall, but an o-scope reading of all pins in question show expected voltage with very low noise.

 

@LCE:

I probably would have also, brain flip ;)

As above, definitely configured for single-ended.

 

I'll update the original post with all this additional info.

> I'll post a screenshot (or a few) of my register readouts for ADC1 and ADC123_Common in the original post.

OK so you've posted a screenshot, where ADC_SQR1=0x1C0, i.e. one conversion and that's on channel 7; and ADC_DIFSEL=0x80, which means the conversion on channel 7 is differential.

The mcu does not work out of what you've clicked in CubeMX, it works out of the registers' content.

JW

So I guess when you configure one channel, you don't configure them all ;)

Thank you so much for that!

At ground, measuring 0x000.

At 3.3V, measuring 0xFFF.

At the middle of a 1/2 resistor divider, 0x7FF.