Getting Started with STM32H5 ARM Cortex M33: ADC Single Channel Single Conversion 

In this guide on STM32H5, we shall configure the ADC of the STM32H5 to acquire analog voltage using polling mode.

In this guide, we shall cover the following:

  • What is ADC.
  • STM32CubeMX Setup.
  • Firmware development.
  • Results.

1.1 What is the ADC

In electronics, an analog-to-digital converter (ADCA/D, or A-to-D) is a system that converts an analog signal, such as a sound picked up by a microphone or light entering a digital camera, into a digital signal that can be read by STM32. 

ADCs can vary greatly between microcontroller. The ADC on the STM32F411 is a 12-bit ADC meaning it has the ability to detect 4096(2^12) discrete analog levels (which is also called Resolution). Some microcontrollers have 8-bit ADCs (2^8 = 256 discrete levels) and some have 16-bit ADCs (2^16 = 65,536 discrete levels).

The way an ADC works is fairly complex. There are a few different ways to achieve this feat (see Wikipedia for a list), but one of the most common technique uses the analog voltage to charge up an internal capacitor and then measure the time it takes to discharge across an internal resistor. The microcontroller monitors the number of clock cycles that pass before the capacitor is discharged. This number of cycles is the number that is returned once the ADC is complete. Other methods used called Successive-approximation ADC which you can read about it in details from this wikipedia page (Link)

For more information about how the adc of STM32F4 works, refer to the user manual (RM0383).

1.2 Relating ADC Value to Voltage

The ADC reports a ratio metric value. This means that the ADC assumes 3.3V is 4095 and anything less than 3.3V will be a ratio between 3.3V and 4095.

For example if the sensor has output voltage of 1.66V hence the ADC output will be (4095/3.3)*1.66=2059.

2. STM32CubeMX Setup:

We start off by creating new project and name it adc_single. For how to create new project, please refer to this guide here.

After creating the new project, we shall first find the pins for the ADC.

Since STM32H563ZI Nucleo-144 has arduino pins, we can find the A0 of the arduino pin is connected to PA6 as following:

Hence, we shall configure PA6 of STM32 as ADC1_INP3 as following:

Since there are multiple ADC modules within the STM32H5, you can select ADC1 or ADC2. In this guide, we shall focus on ADC1.

From left side, select ADC1 and enable Channel 3 in single ended mode as following:

From the parameter settings, we shall modify the overrun behaviour to be overrun data overwritten as following:

Thats all for the ADC section.

Also, enable the UART since we shall use it to print the ADC data to the serial terminal application.

For how to enable serial and retarget printf, please follow this guide here.

Save the project and this shall generate the code.

3. Firmware Development:

After the code has been generated, we shall start the ADC in the while loop.

In user code begin 3 in while loop, we shall start the adc as following:

HAL_ADC_Start(&hadc1);

Note: If you are using other ADC, replace the hadc1 to the hadcx where x is the ADC module number.

Next, we shall poll for conversion and check if the conversion has completed before timeout or not as following:

if(HAL_ADC_PollForConversion(&hadc1, 100)==HAL_OK)

The HAL_ADC_PollForConversion will check if the ADC has finished the conversion by waiting for the end of the conversion flag to be set. The function takes two parameters:

  • Pointer to adc handletype def which is hadc1 in our case.
  • Time out which is 100 milliseconds in out case.

If the result of the function is HAL_OK which means the ADC has successfully converted the data, we we shall get the data as following:

uint16_t adc_value=HAL_ADC_GetValue(&hadc1);

HAL_ADC_GetValue will return the ADC value and we shall store it variable called adc_value.

Next, print the adc value using printf as following:

printf("ADC Value =%d\r\n",adc_value);

Outside the if function:

Delay by half second between each reading as following:

HAL_Delay(500);

Hence, the code within the while loop as following:

	  HAL_ADC_Start(&hadc1);
	  
	  if(HAL_ADC_PollForConversion(&hadc1, 100)==HAL_OK)
	  {
	 	uint16_t adc_value=HAL_ADC_GetValue(&hadc1);
	 	printf("ADC Value =%d\r\n",adc_value);
	  }
	  HAL_Delay(500);

That all for the guide.

Save the project, build it and run it on your STM32H563Zi board.

4. Results:

Open your serial terminal application, set the baud rate to be 115200 and you should get the following:

Happy coding 😉

Add Comment

Your email address will not be published. Required fields are marked *