ADC measurements recommendations

1. Introduction

The ADC (Analog-to-Digital Converter) on STM32 microcontrollers is a crucial peripheral for converting analog signals into digital values, enabling applications such as DC measurements (e.g., temperature sensing, battery monitoring) and AC measurements (e.g., audio signal acquisition, waveform analysis). Proper ADC configuration is essential to ensure accurate and reliable results.

This wiki provides an overview of the key parameters and the features required for ADC configuration in each type of measurement. It also covers post-processing techniques like normalization, filtering, and averaging to enhance signal quality and reduce noise. Additionally, evaluation methods for analyzing conversion errors are discussed to help users assess and optimize ADC performance.

To bridge theory and practice, practical examples are provided for DC, AC, Phase and Rise time measurements, demonstrating how to configure the ADC for various use cases. By following this guide, readers will gain the knowledge needed to configure, optimize, and evaluate ADC performance on STM32 boards effectively.

2. ADC features overview

The ADC features are generally related to specific ADC functionalities that we want to enable or disable. These features determine how the ADC will operate in terms of behavior and system interactions. Some of them are listed below.

ADC features Overview
ADC Features Overview
General I/O Core Power
  • Technology: SAR, Sigma-delta
  • Configurable sampling time
  • Functional mode: ADC dual mode, Single, Continuous, Scan, Discontinuous, or Injected
  • Special function: Hardware oversampling, analog watchdogs
  • Product package: QFP, BGA
  • ADC units: Number of modules
  • Input channel: N of channels, Single/Differential
  • Internal channels: Tsensor, VREFin and VBAT
  • Channel type: Slow, Fast, Direct
  • ADC Vref+: Dedicated or shared pin VDDA
  • Triggers: Software, internal timer event
  • Interrupts: end of conversion.
  • Resolution
  • Calibration: Offset, Linearity
  • Oversampling
  • Data alignment
  • Data processing: Interrupt generation, DMA requests
  • Low-power modes: Deep power-down, auto delay, power consumption dependent on speed

3. ADC parameters overview

ADC parameters define the technical and numerical settings of the peripheral. They determine the performance and accuracy of the ADC, as well as how the converted data will be handled. Some of them are listed below.

ADC parameters overview
ADC Parameters Overview
Range Frequency DC Accuracy AC Accuracy
  • Vref range
  • Input range and common mode
  • Full Scale Range (FSR)
  • Sampling time
  • ADC frequency
  • Offset Error (OE)
  • Gain Error (GE)
  • Differential Non - Linearity (DNL)
  • Integral Non - Linearity (INL)
  • Total Unadjusted Error (TUE)
  • Total Harmonic Distortion (THD)
  • Signal-to-Noise (SNR)
  • Signal-to-Noise and Distortion (SINAD)
  • Spurious Free Dynamic Range (SFDR)
  • Idle channel noise (ICN)

4. ADC post-processing methods overview

Post-processing methods refer to a set of techniques or operations applied to data, images, signals, or results after the primary processing or analysis has been completed. These methods are commonly used to refine, enhance, or interpret the output, making it more useful, accurate, or visually appealing.

Among the methods, there are those performed in hardware and those implemented in software - the latter offering greater flexibility but requiring more of CPU usage and processing time. Some of them are listed below.

Post-processing methods
Post-Processing methods
Hardware - Based methods Software - Based methods
  • Oversampling;
  • Right/Left bit shifting;
  • Hardware averaging;
  • Offset correction;
  • Gain compensation;
  • Analog watchdog;
  • Data thresholding;
  • Injected conversion post-processing;
  • Automatic calibration.
  • Averaging: Standard or quantile;
  • Filtering;
  • Decimation;
  • Interpolation;
  • Amplification;
  • Demodulation;
  • Integration;
  • Differentiation;
  • Fourier transform;
  • Wavelet transform;
  • Peak or Zero-crossing detection.

5. ADC measurement recommendations details

6. Constant voltage or DC voltage measurement

The following table presents recommendations on the configuration of the ADC for the DC measurement context. Before following the recommendations, check the product datasheet and reference manual to ensure compatibility with our recommendations.

ADC measurement configuration - DC voltage measurement
ADC

Features

Mandatory Recommended Optional
  • Perform offset calibration to reduce natural ADC offset (AN2834 - 3.1.1)[1].
  • Load linearity calibration coefficients: for best full-range accuracy (AN5354 - 2.5.2) [2].
  • Use the maximum resolution available: DC accuracy depends on
    • (N = ADC resolution).[3]
  • Utilize DMA: For high-speed data transfer, minimizing CPU load.
  • Use single mode for basic measurements or continuous mode for real-time monitoring.
  • Use ADC DMA interrupt: For efficient data handling and processing.
  • Use ADC Vref+ dedicated pin: it ensures stability in the reference voltage.
  • Use polling conversion for basic measurements.
  • Use differential channels for noise immunity.
  • Implement hardware oversampling for accuracy.
  • Use Scan Mode with DMA for multiples channels application.
  • Use ADC interrupt: For efficient processing.
  • Multi-Channel Synchronization ensures simultaneous, consistent multi-ADC measurements.
  • Use Analog Watchdogs to monitor samples within set limits for protection or control.
ADC

Parameters

  • Use highest ADC sampling time (SMP) for best performance (AN2834 - 4.2.6)[3].
  • Ensure input range covers expected DC voltage levels.
  • Check TUE parameter in datasheet.
Post Processing
  • Use oversampling for improved accuracy.
  • Use oversampling and averaging for improved accuracy: Usage of standard averaging or quantile method to reduce the presence of noise[4].
  • Implement averaging filter to reduce noise and improve measurement quality
Application design
  • Vref DC accuracy <0.1%: if Vref unmeasurable, use external reference like LM4040A.
  • Stable Vref for better accuracy.
  • Signal Conditioning to fit ADC input range:
    • Scale signals with voltage dividers/amplifiers.
    • Add filters to reduce noise/ripple.
  • Follow max RAIN input impedance from datasheet, especially for high-impedance sources.
  • Use decoupling capacitors per datasheet to reduce supply noise and stabilize operation.
  • Ensure the Vin is as close as possible to Vref.
  • Low Vref voltage decreases LSB.
  • Low-Pass Filtering: to remove high-frequency noise or ripple.
  • Add signal clipping protection (e.g. diodes) to safeguard the microcontroller.
Verification

Methods

  • Use static for basic error analysis.
  • Use histogram to visualize data distribution and compare with normal distribution.

6.1. Example of measurement - Static or DC voltage

To illustrate constant voltage measurements using an ADC, measurements were taken using a DAC as the voltage generator being internally connected (on-chip analog peripheral) to the ADC.

Setup of DC measurement

As illustrated in the schematic above, a multimeter was used to verify the voltage applied to the ADC input. Therefore, for this analysis, errors or noise originating from the DAC were not considered; only the DAC output voltage itself was taken into account.

The primary objective of this experiment is to evaluate the accuracy of DC voltage measurements using the STM32H7A3ZI-Q ADC. The ADC was properly configured by following the previously outlined recommendations. Subsequently, measurement errors were calculated, and verification methods were applied to ensure reliable results.

To thoroughly assess the ADC’s good configuration across its input range, measurements were performed at three distinct voltage levels—low, medium, and high. In the following section, the ADC configuration, the experimental code developed using STM32CubeMX and STM32CubeIDE, and a step-by-step procedure for data acquisition are detailed.

6.1.1. Acquired raw data - Low, Medium, High voltage measurements

Following the guidelines provided on the Wiki page, the table below provides the configurations used in the experiment.

Key parameters of the ADC
Board Nucleo Package Power supply (VDDA) VREF voltage ADC frequency Sampling Time ADC Features Post Processing method Verification Method
H7A3ZI - Q QFP 3.3 V 3.302 V 5 MHz 810.5 cycles
 • Single ended channel
 • Slow channel
 • 12-bits resolution
 • Continuous Mode
 • Offset Calibration
 • Linearity Calibration
 • Averaging
 • Total Unadjusted Error (TUE)
 • Statistic histogram

Next, for the first analysis, a buffer adc_dma_buffer[16] was created to store the values of each ADC conversion; in this case, it was collected 16 values for each measurement.

For the second analysis, the histogram data was stored in "full_adc_histogram[4096]. In the last mentioned case, for each code value (represented by the buffer position number), the number of times it appears. The code below shows the lines of code that were added. Note that calibration and load calibration were performed before the conversion.

#include <stdio.h>
#include <string.h>

#define NUM_CODE 4096
#define ADC_BUFFER_SIZE 16
#define NUM_SAMPLES 1

volatile uint32_t samples_collected = 0;

uint16_t full_adc_histogram[NUM_CODE];
uint16_t adc_dma_buffer[ADC_BUFFER_SIZE];
volatile uint8_t conversion_complete = 0;

/* Main program entry point */
int main(void)
{
    /* USER CODE BEGIN 1 */
    /* USER CODE END 1 */

    /* MPU Configuration--------------------------------------------------------*/
    MPU_Config();

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */
    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */
    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_ADC1_Init();
    MX_DAC1_Init();
    MX_OPAMP1_Init();
    MX_USART3_UART_Init();
    MX_TIM6_Init();

    /* USER CODE BEGIN 2 */

    // Histogram initialization
    for (uint16_t i=0; i <ADC_BUFFER_SIZE;i++)
    {
 	  full_adc_histogram[i]=0;
    }

    samples_collected =0;
    
    
    <!--      ------------------------------------------------------------------
      Perform raw data acquisition for specific DAC codes
      Low voltage - dac_code = 90, Medium voltage - dac_code = 2000 and 
      High voltage - dac_code = 4000 
      -------------------------------------------------------------------->
      
    HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_2, DAC_ALIGN_12B_R, 2000);
    HAL_Delay(100);
    
     if (HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED) != HAL_OK)
	 {
	    Error_Handler();
	 }
	      
    HAL_ADC_Start_DMA(&hadc2, (uint32_t*)adc_dma_buffer, ADC_BUFFER_SIZE);


    while(samples_collected ==0){
 	    //Wait buffer complete
    }

    samples_collected =0;
    HAL_ADC_Stop_DMA(&hadc2);
    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); //to indicate that the conversion finished

   for (uint16_t i = 0; i< ADC_BUFFER_SIZE; i++)
   {
   	  uint16_t adc_value = adc_dma_buffer[i];
   	  if (adc_value < NUM_CODE)
   	  {
   	  	full_adc_histogram[adc_value]++;
   	  }
   	  samples_collected++;
   	}
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
/* Function to indicate that the conversion is finished and the histogram can be collected*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	samples_collected = 1;

}
/* USER CODE END 4 */

To collect the histogram data, we directly access the microprocessor's memory. For this, it is first necessary to know the address where the "full_adc_histogram" buffer is located (use the file shown below).

Data acquisition - STM32CubeIDE

Then, the STM32Programmer software is used to transfer the memory data (in binary) to a binary file so that the data can be processed. In this way, the following commands are used in the command prompt.

#1 Open "Command Prompt" and past the STM32_CubeProgrammer_CLI.exe PATH:
ex: cd "C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin"

#2 Run the update of the embedded ST-Link debugger (optional)
STM32_Programmer_CLI.exe -stlink_fwupdate

#3 Save firmware variable to file: STM32_Programmer_CLI --connect port=<PORT_TYPE> -u <ADDRESS> <SIZE> <FILE_PATH>
ex: STM32_Programmer_CLI --connect port=SWD -u 0x240002ac 0x2000 c:\Temp\fw_variable_content_file.bin

#Attention: before executing command 3, stop the debugger.

Once the data was collected, an error analysis was conducted to quantify the measurement accuracy using Octave software for example.

6.1.2. Measurement accuracy analysis methodology

Total Unadjusted Error Analysis

For a first analysis of the error under the measurements performed (low, medium, and high voltage), a standard average of the acquired codes is performed and compared with the theoretical value. These are calculated as follows:

, where is the voltage measured with a multimeter, is the reference voltage and N is the ADC resolution.

Finally, for the calculation of the error:

Info white.png Information
For more details on how to improve the accuracy of the ADC and the types of errors it is susceptible to, read AN2834.

Histogram and normal distribution noise analysis

For the second analysis, the process begins with standard averaging, where multiple ADC samples are collected and averaged to calculate a stable mean value. This averaging reduces random noise and transient fluctuations inherent in individual readings, resulting in a more reliable representation of the true DC voltage.

Following the calculation of the average, a histogram of the sampled data is constructed. This histogram visually represents the distribution of ADC codes, highlighting the frequency of each code acquired. Analyzing this distribution provides insight into the noise characteristics and stability of the measurement system.

A crucial step in this methodology is the comparison of the histogram with a Gaussian (normal) distribution. This comparison is justified because the predominant noise sources in electronic measurements—such as thermal noise and quantization noise—typically follow a normal distribution due to the central limit theorem. Confirming that the ADC sample distribution approximates a Gaussian shape validates the assumption of random, unbiased noise and indicates proper ADC configuration.

6.1.3. Results - DC voltage measurement

The results of the first TUE analysis are shown in the following figure.

As a first DC measure, a low voltage of 0.07422V was applied and a TUE = -5.04 LSB was obtained, as indicated in "Error (AVG)".

Raw data - low voltage value.png

Such measurement will be compared with the value from the data sheet at the end of this section.

As a second DC measure, a medium ADC input voltage of 1.65131 V was applied and a TUE = -0.31 LSB was obtained, as indicated in "Error (AVG)".

Raw data - medium voltage value.png

Such measurement will be compared with the value from the data sheet at the end of this section.

As the last DC measure, a high ADC input voltage of 3.2247 V was applied and a TUE = 4.68 LSB was obtained, as indicated in "Error (AVG)". Raw data - high voltage value.png

Analyzing the results obtained and comparing them with the product’s data sheet (slow channel -> single ended), it can be stated that the accuracy is within the expected error value:

  • Low voltage: -10 LSB < -5.04 LSB < 10 LSB
  • Medium voltage: -10 LSB < -0.31 LSB < 10 LSB
  • High voltage: -10 LSB < 4.68 LSB < 10 LSB
ADC accuracy  - data sheet (STM32H7A3ZI)


For the histogram analysis, we consider an error of±2% as good, meaning the measurement is highly accurate with minimal deviation from the expected value, ±5% as moderate, meaning the measurement has some noticeable deviation but is still acceptable for many practical purposes and ±10% as poor, meaning the measurement shows significant deviation and is generally not reliable.

The following graphs show 3 types of analysis:

  1. Error between the mean value of the distribution (dark blue dashed line) and the theoretical expected value for the input voltage applied (pink dashed line).
  2. Comparison between the normal (Gaussian) distribution (yellow curve) and the obtained distribution (bar graph), highlighted by black crosses.
  3. Comparison between the mean value of the Gaussian (green line) and the mean value of the obtained distribution (dark blue dashed line).

Thus, it was obtained the results below:

For the first measurement at low voltage (0.07422 V), we obtained the following result (TUE=-4.05 LSB):

New histogram low voltage dma.png

In figure, we follow the methodology explained previously. The yellow curve shows the normal distribution of the obtained codes, taking into account the expected noise. As can be seen, it deviates only slightly from the measured distribution (black marks indicate the values crossing the Gaussian curve). Thus, the mean of the 4096 values obtained was calculated and compared with the theoretical mean (input value to the ADC in LSB).

The error percentage remains within ±2%, which classifies it as a good result.

For the measurement at medium voltage (1.65131 V), we obtained the following result (TUE=0.61 LSB):

Histogram - Medium voltage

As can be seen, it also deviates only slightly from the measured distribution (black marks indicate the values crossing the Gaussian curve). Thus, the mean of the 4096 values obtained was calculated and compared with the theoretical mean (input value to the ADC in LSB).

The error percentage remains within ±2%, which classifies it as a good result in medium voltage.

For the measurement at medium voltage (3.2247 V), we obtained the following result (TUE=1.03 LSB):

New histogram high voltage dma.png

As can be seen, it also deviates only slightly from the measured distribution. Thus, the mean of the 4096 values obtained was calculated and compared with the theoretical mean.

The error percentage remains within ±5%, which classifies it as a moderate result in high voltage.

6.1.4. Conclusion - DC voltage measurement

In conclusion, the experiment shows that for all three measurements, the obtained real distributions are similar to the expected normal distributions. Furthermore, as observed in the first analysis, the error values are within the established tolerance and comply with the specifications set by the datasheet. This indicates a good ADC configuration and, consequently, an efficient measurement of DC voltage.

The advantages of this approach are multifold:

  • It enables the identification of systematic errors or anomalies that deviate from expected noise behavior.
  • It provides a quantitative basis for estimating measurement uncertainty and ADC resolution effectiveness.
  • It supports the optimization of ADC configuration and signal conditioning by revealing noise patterns and potential distortions.

By combining averaging, histogram analysis, and Gaussian comparison, this methodology offers a robust framework for evaluating and improving the accuracy of DC voltage measurements using ADCs.

7. Dynamic or AC voltage measurement

The following table presents recommendations on the configuration of the ADC for the AC measurement context. Before following the recommendations, check the product datasheet and reference manual to ensure compatibility with our recommendations.

ADC measurement configuration - AC voltage measurement
ADC

Features

Mandatory Recommended Optional
  • Use Continuous Mode to collect all samples without interruption.
  • Use DMA for efficient data transfer.
  • Use 12-bit resolution or higher to capture subtle AC variations, especially low amplitudes.
  • Perform offset calibration to reduce ADC offset (AN2834 - 3.1.1)[1].
  • Load linearity calibration coefficients for optimal full-range accuracy (AN5354 - 2.5.2) [2].
  • Use single-ended channels for simple AC signals; use differential channels for differential signals (e.g., current sensors).
  • Use ADC Vref+ dedicated pin for stable reference voltage.
  • Use timer trigger for uniform sampling intervals, essential for accurate AC signal reconstruction and frequency analysis.
  • Use Injected Functional Mode to capture specific AC events on demand.
  • Implement Analog Watchdogs to monitor voltage limits for protection and control.
  • Use Fast channel type for high-frequency AC signals.
  • Use ADC Trigger to synchronize sampling with signal phase for consistent capture.
  • Use Scan Mode to monitor multiple channels simultaneously, e.g., three-phase measurements.
ADC

Parameters

  • Use stable Vref for improved accuracy.
  • Set sampling time fast enough to exceed twice the AC signal frequency (Nyquist theorem).
  • Ensure ADC frequency is high and stable to support required conversion rate.
  • Maintain good Signal-to-Noise ratio (SNR) for quality AC signal capture, especially in noisy environments.
  • Ensure FSR(Full Scale Range) covers the AC signal’s maximum expected amplitude.
  • Prioritize lowest THD (from datasheet) for high-fidelity AC applications.
  • Ensure low INL/DNL for linear ADC conversion across the full range.
  • Use low SFDR for high-sensitivity applications detecting weak signals amid strong ones.
  • Use SINAD to evaluate overall signal quality, especially for complex AC signals.
Post Processing
  • Use peak or zero-crossing detection to find peaks or zero crossings, aiding amplitude and frequency calculation.
  • Use AC RMS measurement as a simple method to measure AC amplitude.
  • Use oversampling.
  • Use filtering (software or hardware). Ensure the maximum Input frequency is lower than Filter cut-off frequency/10 to avoid band attenuation.
  • Apply data thresholding to detect specific AC events like voltage drops or anomalies.
  • Use averaging.
  • Use interpolation to improve temporal resolution, mainly for advanced applications.
  • Use Fourier Transform for essential frequency analysis of AC signals.
Application design
  • Design signal conditioning circuits for AC signals, including:
    • Adding DC offset to fit ADC input range.
    • Using filters to remove noise and unwanted frequencies.
    • Amplifying or attenuating signals to match ADC FSR for optimal resolution.
  • Ensure power supply and voltage stability with low-noise regulators and bypass capacitors.
  • Match input impedance between signal source and ADC to prevent distortion or attenuation.
  • Use differential signal measurement for high precision or noisy environments to reduce common-mode noise and improve signal integrity.
Verification

Methods

  • Histogram Analysis.
  • Linearity testing.
  • Validation with Known Signals (e.g., sinus wave).
  • DNL/INL testing.
  • Harmonic Analysis.
  • Noise and Distortion Testing (SNR and THD).
  • Frequency Response Analysis.
  • Real-Time Data Logging.
  • Automated Test Bench.

7.1. Example of measurement - Dynamic or AC voltage

To illustrate AC measurements using an ADC, measurements were taken using a wave generator to generate a sine wave as shown below. As in the previous example, we can use an external multimeter to measure the external RMS signal voltage and compare it with the acquired adc_dma_buffer.

Measurement AC - setup

At the embedded code level, a buffer "adc_dma_buffer" with a size of 1024 was declared (slightly over 10 cycles of a sine wave at 4 kHz frequency). The buffer stores the resulting code value for each voltage value.

In the following points, the methodology for analyzing the accuracy of the AC measurement performed will be explained.

The step-by-step procedure for data acquisition is detailed below.

Following the guidelines provided on the Wiki page, the table below provide the configurations used in the experiment.

Key parameters of the ADC
Board Nucleo Package Power supply (VDDA) VREF voltage ADC frequency Sampling Time ADC Features Post Processing method Verification Method
H7A3ZI - Q QFP 3.302 V 3.302 V 18 MHz 64.5 cycles
 • Single ended channel
 • Fast channel
 • 16-bits resolution
 • Continuous Mode
 • DMA circular
 • Offset Calibration
 • Linearity Calibration
 • Zero Crossing Detection
 • AC RMS measurement
 • Validation with known signal
 • SNR and THD

Next, a buffer adc_dma_buffer[16] was created to store the values of each ADC conversion; in this case, it was collected 16 values for each measurement. Note that calibration and load calibration were performed before the conversion. The code used shows the lines of code that were added.

#include <stdio.h>
#include <string.h>

#define ADC_BUFFER_SIZE 1024 //dma buffer size

uint16_t adc_dma_buffer[ADC_BUFFER_SIZE];
volatile uint32_t samples_collected = 0;

/* Main program entry point */
int main(void)
{
    /* USER CODE BEGIN 1 */
    /* USER CODE END 1 */

    /* MPU Configuration--------------------------------------------------------*/
    MPU_Config();

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */
    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */
    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_ADC1_Init();
    MX_DAC1_Init();
    MX_OPAMP1_Init();
    MX_USART3_UART_Init();
    MX_TIM6_Init();

    /* USER CODE BEGIN 2 */

    if(HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
  	  Error_Handler();

    if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_buffer, ADC_BUFFER_SIZE) != HAL_OK)
  	  Error_Handler();
      samples_collected =0;


    while(samples_collected ==0){
    	//Wait buffer complete
    }

     samples_collected =0;
     HAL_ADC_Stop_DMA(&hadc1);
     HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
/* Function to indicate that the conversion is finished and the histogram can be collected*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
	samples_collected = 1;
	HAL_GPIO_WritePin(GPIOB, LD1_Pin, GPIO_PIN_RESET);

}
/* USER CODE END 4 */

To collect the raw data, we directly access the microprocessor's memory. For this, the data acquisition ("adc_dma_buffer" data) followed the same methodology as described in the DC voltage measurement section. </syntaxhighlight>

7.1.1. Measurement accuracy analysis methodology

A pure sine wave is commonly used as an input signal for ADC testing because it is a simple, well-defined waveform with a single frequency. This allows precise evaluation of the ADC’s behavior, including the noise and distortion introduced during conversion.

Validating an ADC often involves comparing its output to known theoretical signals like sine waves. This section outlines the key principles and practical steps for performing such validation.

Following this, the analysis extends to evaluating SNR (Signal-to-Noise Ratio) and THD (Total Harmonic Distortion), which are critical metrics for assessing the accuracy and fidelity of the ADC conversion.

Validation with a known signal

Understanding the validation methodology starts with the use of known reference signals. These signals serve as precise benchmarks for comparing ADC outputs, allowing accurate assessment of key performance metrics such as linearity, noise, distortion, resolution, and frequency response. They also help identify issues like offset, gain errors, non-linearity, and saturation, ensuring the integrity of the entire signal processing chain.

This section presents an experimental AC measurement test applying the validation method through the following steps:

1. Plotting the ADC Output Curve; 

2. Zero Crossing Detection;  

3. Theoretical Signal Reconstruction;  

4. Error Analysis;  

5. RMS and Peak-to-Peak (Vpp) Calculation;  

6. Signal with Saturation Analysis.  

Signal - to - Noise Ratio (SNR) and Total Harmonic Distortion (THD)

SNR quantifies the ratio between the power of the desired signal and the power of background noise present in the output. It is expressed in decibels (dB) and defined as:

where:

  • is the power of the fundamental sine wave component.
  • is the power of all noise components excluding the fundamental frequency.

A higher SNR indicates that the ADC output is dominated by the true signal with minimal noise interference, reflecting better conversion accuracy and resolution. In practical terms, SNR helps assess the ADC’s ability to distinguish the input signal from noise sources such as thermal noise, quantization noise, and other electronic interferences.

THD measures the distortion introduced by the ADC by quantifying the presence of harmonic frequencies generated during the conversion process. It is the ratio of the sum of powers of all harmonic components (integer multiples of the fundamental frequency) to the power of the fundamental frequency itself:

where:

  • is the power of the fundamental frequency.
  • is the power of the power of the n-th harmonic frequency.

Lower THD values indicate that the ADC introduces minimal nonlinear distortion, preserving the purity of the input sine wave.

7.1.2. Results - AC voltage measurement

The first step is data acquisition. Raw ADC data were acquired and processed in Octave, as shown in the previous section. The digital codes were converted into voltage values using the known sampling frequency, allowing the reconstruction of the analog input waveform for visualization and analysis.

ADC output signal

After centering the signal, we can already observe that the signal amplitude is consistent with the expected results (shown in the figure of the AC measurement setup - Vpp = 1V).

Next, to facilitate the calculation of RMS and Vpp (calculation shown in step 4), it is necessary to perform a zero-crossing method by analyzing 10 periods. Additionally, the sine waveform generated by the Hilbert transform (shifted by 90°) was compared with the signal waveform (comparison analysis in step 3). ADC output signal - 10 periods

By comparing the resulting waves — the ideal sine wave (in dark blue) and the obtained sine wave (in light blue)— analyzing the graph below, we found a maximum error of approximately 3.47% .

ADC output signal - 10 periods

The figure above shows the graph of the percentage error. By analyzing the second figure, we can confirm the accuracy of the measurement performed, knowing that most of the time the percentage error stays below 2%. Even when it exceeds this limit, it remains between 2% and 5%, which may still be acceptable for some applications. The error is also within the specifications outlined in the datasheet.

The Root Mean Square (RMS) value of the segmented 10-period signal was calculated to quantify its effective amplitude. From the RMS, the peak-to-peak voltage (Vpp) was derived using the appropriate mathematical relationship for sinusoidal signals.

Calculating the RMS value and Vpp using the Octave software, we obtained the following results:

Consistent with the input signal and the expected signal (shown in the figure of the AC measurement setup - Vpp = 1V).

The graph below presents an analysis of signal distortion using FFT (Fast Fourier Transform) on the ADC output. The FFT reveals the frequency spectrum of the input signal, clearly highlighting the fundamental frequency as the dominant peak, confirming accurate signal capture. In the graph, the fundamental frequency appears at 4093.61 Hz with a magnitude of -13.85 dB, indicating its predominance.

FFT of the output signal - 10 periods

Harmonic peaks at integer multiples of the fundamental frequency represent nonlinear distortion introduced during conversion. Quantifying these harmonics allows calculation of the Total Harmonic Distortion (THD), a direct measure of signal purity. A low THD value indicates minimal distortion and high linearity of the ADC. The noise level observed in the FFT spectrum enables calculation of the Signal-to-Noise Ratio (SNR), reflecting the ADC’s ability to distinguish the input signal from background noise.

Together, the FFT, THD, and SNR metrics provide a comprehensive evaluation of ADC performance, confirming its suitability for high-fidelity signal acquisition. In this case, the ADC achieved a THD of 0.09% and an SNR of 62.70 dB.

Since the acquisition was performed using the DMA One-shot mode (single acquisition), the FFT results are notably affected by noise, as indicated by the SNR. To improve measurement quality, the FFT Video Averaging method was employed. This technique averages multiple acquisitions point-by-point, enhancing the harmonic components while reducing noise, as noise averages toward zero and periodic signals remain stable.

The figure below illustrates the improved spectrum obtained using this averaging technique.

FFT with video averaging applied - 10 periods

7.1.3. Example of an anomaly case in the input signal

To analyze non-ideal conditions, the same analysis workflow was applied to a signal intentionally saturated over a specific time interval. This allowed evaluation of the impact of saturation on measurement accuracy and error characteristics.

ADC satured signal error

Next, the high THD indicates the presence of nonlinearity and distortion, with a THD of 4.77% and an SNR of 32.35 dB (always consult the product datasheet to compare and validate the results).

FFT saturated signal without DC (THD and SNR)

This result is significantly below the expected values indicated in the datasheet, confirming the presence of anomalies at the input.

7.1.4. Conclusion - AC voltage measurement

To conclude, following the Wiki recommendations for AC measurements, efficient data acquisition was achieved. Using zero crossing for data selection and RMS calculation for Vpp determination proved effective. Validation of raw data via Hilbert transform, along with SNR and THD calculations, enabled a precise analysis of measurement accuracy. This approach allows consistent verification of ADC noise performance and linearity, identification of distortion sources, and ensures compliance with design and quality standards.

It is worth noting that, in FFT analysis of a signal acquired in DMA one-shot mode, it becomes necessary to perform software-based oversampling methods followed by averaging to highlight the signal harmonics, preventing them from being mistaken for noise.

This methodology provides a quantitative and repeatable way to:

  • Verify the ADC’s noise performance and linearity.
  • Identify potential sources of distortion or interference.
  • Ensure compliance with design specifications and quality standards.

8. Phase (or delay) and Rise time measurement

The following table presents recommendations on the configuration of the ADC for the phase measurement context. Before following the recommendations, check the product datasheet and reference manual to ensure compatibility with our recommendations.

ADC measurement configuration - Phase measurement
ADC

Features

Mandatory Recommended Optional
  • Use Continuous Mode to collect all samples without interruption.
  • Use DMA for efficient data transfer.
  • Use 12-bit resolution or higher for sufficient phase accuracy.
  • Use ADC Vref+ dedicated pin dedicated pin for stable reference voltage.
  • Use Timer trigger to synchronize sampling with signal phase.
  • Use Scan Mode to monitor multiple channels simultaneously (e.g., multi-phase systems)
  • Use Hardware Oversampling if available to improve SNR and reduce noise.
  • Implement Analog Watchdogs to monitor voltage limits for protection and control.
  • Use Injected Conversion Mode to capture specific phase events on demand.
ADC

Parameters

  • Use stable Vref for improved accuracy.
  • Set sampling time long enough for accurate capacitor charging.
  • Ensure ADC frequency is high and stable to support required conversion rate.
  • Prioritize high SNR (from datasheet) for high-fidelity AC applications.
  • Ensure low INL/DNL for linear ADC conversion across the full range.
  • Use low SFDR for high-sensitivity applications detecting weak signals amid strong ones.
  • Use SINAD to evaluate overall signal quality, especially for complex AC signals.
Post Processing
  • Use peak or zero-crossing detection to find peaks or zero crossings, aiding amplitude and frequency calculation.
  • Apply filtering to reduce noise and avoid aliasing.
  • Use oversampling. and averaging to improve effective resolution and reduce noise.
  • Use filtering (digital or analog). Ensure 10×Fin > Fc to avoid band attenuation.
  • Use interpolation to improve temporal resolution between samples.
  • Use data thresholding to detect phase-related anomalies events.
  • Apply advanced transforms (wavelet, etc.) for complex phase behavior analysis.
Application design
  • Design signal conditioning circuits with proper filtering and impedance matching.
  • Ensure power supply and voltage stability with low-noise regulators and bypass capacitors.
  • Use amplifiers/attenuators to scale signals within ADC input range.
  • Use differential signal measurement for high precision or noisy environments to reduce common-mode noise and improve signal integrity.
  • Use shielding and grounding to minimize EMI and noise.
Verification

Methods

  • Validation with Known Signals (e.g., sinus wave).
  • DNL/INL testing.
  • Harmonic Analysis (THD).
  • Frequency Response Analysis.
  • Real-Time Data Logging.

8.1. Example of measurement - Phase (or delay) and Rise time

As an example of a phase measurement, the following experiment was conducted by applying two out-of-phase trapezoidal signals at the ADC input, with different amplitudes and offsets relative to each other.

schematic phase meas.png

For data acquisition, a comparator was added to one of the ADC inputs so that it triggers a flag (COMP_IT) when the input voltage equals Vref/4. At the beginning of the process, the ADC will be initialized and will start converting the input signals continuously, and the dma_buffer data will be saved in the data_buffer_0 and data_buffer_1 registers (each stores information for half of the DMA buffer). The data will be written and rewritten until an interrupt occurs.

When the comparator interrupt is triggered, the ADC will stop the conversion, and the data stored in data_buffer_0 and data_buffer_1 will be stored in a new register called data_complete, where the order in which they are concatenated will depend on the moment the interrupt occurred, that is, the position in the DMA buffer where the conversion data was being saved when the interrupt happened.

As a form of validation, the rise times of the two output signals were compared with the input signals, as well as the phase shift, among other verification methods that will be detailed in the following sections.

The step-by-step procedure for data acquisition is detailed.

The first step for data acquisition was setting up the ADC, as specified in the table below, using CubeMX.

Key parameters of the ADC
Board Nucleo Package Power supply (VDDA) VREF voltage ADC frequency Sampling Time ADC Features Post Processing method Verification Method
H7A3ZI - Q QFP 3.302 V 3.302 V 25 MHz with prescaler of 64 1.5 cycles
• Single ended channel
• Fast channel
• 12-bits resolution
• Continuous Mode
• Scan Mode
• DMA conversion - Circular Mode
• DMA circular
• Offset Calibration
• Linearity Calibration
• Number of conversion = 2
• Conversion launched by software
• Signal normalization
• Signal synchronization
• Rise time comparison
• Validation with known signals

Next, a buffer adc_dma_buffer[1024] was created to store the values of each ADC conversion. Note that calibration and load calibration were performed before the conversion. The code used shows the lines of code that were added.

#include <stdio.h>
#include <string.h>

#define TAILLE_BUFFER 512
#define TAILLE_TOTAL 1024

uint16_t dma_buffer[TAILLE_BUFFER];
uint16_t data_buffer_0[TAILLE_BUFFER];
uint16_t data_buffer_1[TAILLE_BUFFER];
uint16_t data_complete[TAILLE_TOTAL];
volatile uint32_t comp_IT = 0;
volatile uint32_t dest_buffer = 0;
volatile uint32_t half_complete = 0;
volatile uint32_t full_complete = 0;
volatile uint32_t COMP1_IT_unmask=0;
volatile uint32_t COMP_IT_during_halftransfer=0;
volatile uint32_t COMP_IT_during_fulltransfer=0;
volatile uint32_t buffer_recording=1;

void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp);
void copy_half_buffer(uint16_t* dest, uint16_t* src, uint16_t start, uint16_t end);
void copy_full_buffer(uint16_t* dest, uint16_t* src, uint16_t offset);

/* Main program entry point */
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MPU Configuration--------------------------------------------------------*/
MPU_Config();

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_COMP1_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);


HAL_COMP_Start_IT(&hcomp1);


HAL_Delay(10);
COMP1_IT_unmask=1;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)dma_buffer, TAILLE_BUFFER);

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

if (buffer_recording)
{
uint16_t* target_buffer = (dest_buffer == 1) ? data_buffer_1 : data_buffer_0;
uint16_t half_size = TAILLE_BUFFER / 2;

if (half_complete)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
copy_half_buffer(target_buffer, dma_buffer, 0, half_size);

if (comp_IT == 1)
{
COMP_IT_during_halftransfer = 1;
comp_IT = 0;
COMP1_IT_unmask = 0;
}
half_complete = 0;
}

if (full_complete)
{
copy_half_buffer(target_buffer, dma_buffer, half_size, TAILLE_BUFFER);

if (COMP_IT_during_halftransfer || COMP_IT_during_fulltransfer)
{
buffer_recording = 0;
}
else if (comp_IT == 1)
{
COMP_IT_during_fulltransfer = 1;
comp_IT = 0;
COMP1_IT_unmask = 0;
}

dest_buffer = !dest_buffer; // Toggle buffer
full_complete = 0;
}
}
else // buffer_recording == 0
{
// Copy first half from current destination buffer
if (dest_buffer)
{
copy_full_buffer(data_complete, data_buffer_1, 0);
copy_full_buffer(data_complete, data_buffer_0, TAILLE_BUFFER);
}
else
{
copy_full_buffer(data_complete, data_buffer_0, 0);
copy_full_buffer(data_complete, data_buffer_1, TAILLE_BUFFER);
}

while (1)
{
HAL_Delay(150);
// HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
    }
    /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
/* USER CODE BEGIN 4 */
void HAL_COMP_TriggerCallback(COMP_HandleTypeDef *hcomp)
{
if (hcomp->Instance == COMP1)
{
if(COMP1_IT_unmask)
{
comp_IT = 1;
}
}
}

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
{
half_complete = 1;
;
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
full_complete = 1;

}

void copy_half_buffer(uint16_t* dest, uint16_t* src, uint16_t start, uint16_t end)
{
for (uint16_t i = start; i < end; i++)
{
dest[i] = src[i];
}
}

void copy_full_buffer(uint16_t* dest, uint16_t* src, uint16_t offset)
{
for (uint16_t i = 0; i < TAILLE_BUFFER; i++)
{
dest[i + offset] = src[i];
}
}
/* USER CODE END 4 */

To collect the raw data ("data_complete"), we directly access the microprocessor's memory.

When the comparator interrupt is triggered (as mentioned at the Setup of Phase measurement), the data recording process in the buffers is halted, and the data is retrieved. However, since the ADC conversion runs continuously in scan mode, the exact moment when data capture occurs is unpredictable. Therefore, the data may be fully captured during the complete filling of the DMA buffer, but two other scenarios can also occur:

  1. Interrupt occurs in the first half of the buffer: In this case, data prior to the comparator interrupt may be lost.
  2. Interrupt occurs in the second half of the buffer: Here, data after the comparator interrupt may be lost once the DMA buffer is completely filled.

To address this, two buffers (data_buffer_0 and data_buffer_1) are used alternately to store the ADC conversion data. The diagram below summarizes this data acquisition methodology.

schematic embedded code.png

For case 1, the two buffers are concatenated to recover data from conversions (n-1) and n. For case 2, the buffers are concatenated to recover data from conversions n and (n+1).

This approach ensures complete acquisition of the signals and enables accurate reconstruction of the acquired data.

The diagram below shows in detail the operations performed in the embedded code. timeline phase wiki.png

8.1.1. Measurement accuracy analysis methodology

To ensure precise and reliable phase measurement using the ADC of the STM32H7A3ZI-Q, a systematic methodology combining experimental acquisition and data processing was implemented.

First, the input signals were simultaneously applied to both the device under test and a reference oscilloscope, allowing direct capture of the original waveform. ADC data was collected and stored for subsequent analysis.

Before calculating the rise time and applying the threshold crossing method, the signals were normalized to a common scale. This normalization step ensures that amplitude variations do not affect the timing measurements, providing a consistent basis for comparison. Then, using the threshold crossing method, the rising points at 10% and 90% of the maximum value of the trapezoidal signal were collected. With this data, it is possible to calculate the rise time (the same method used by the oscilloscope employed as a reference).

The phase difference between signals was then calculated using the threshold crossing method at 50% of the total amplitude. This approach defines a consistent and stable reference point on the signal’s rising edge, minimizing errors caused by noise or amplitude fluctuations.

The same threshold crossing calculation was applied to both the oscilloscope data and the ADC output data, enabling a direct comparison between the two measurement sources. This process validated the ADC’s ability to accurately capture both the phase shift and the rise time of the input signals, confirming that the digital acquisition system faithfully reproduces the temporal characteristics of the analog signals.

8.1.2. Results - Phase (or delay) and Rise time measurements

The first step was setting up the ADC and acquiring raw data, as specified in the previous section. Post-processing was then performed using Octave software.

Since the ADC was configured in Scan Mode to sequentially acquire data from multiple input channels, the complete data vector (data_complete) was divided into two separate vectors to separate the signals from each channel: one containing the samples at odd indices and the other containing the samples at even indices. The resulting waveforms for each channel are shown in the graphs below.

Trapezoidal input signals - Raw data

An initial analysis of the input signals was performed using an oscilloscope to obtain a direct visualization of the waveform characteristics. Subsequently, a more precise analysis was conducted using Octave software. For improved signal quality and accurate measurement, the signals were filtered in Octave using a 4th-order Butterworth filter, followed by a moving average filter. The filtered signals are presented in the following graph.

Entry signals analyzed via oscilloscope

We can already observe that the signal amplitude is consistent with the expected result, comparing the data acquired and the oscilloscope data. To analyze and compare the original input signal and the signal resulting from the ADC conversion, it was necessary to resample the raw data so that they had the same time scale. Additionally, the oscilloscope signals were shifted to have the same origin (0.0).

Before further processing, the signals were normalized to a common amplitude scale to ensure the threshold points corresponded in both signals. To calculate the rise time, the time interval between the points where the input voltage reaches 10% and 90% of its maximum value was measured. This metric provides a robust characterization of the signal’s transition speed.

Normalized signals - Rise time analysis

Extracting the points where the dashed line crosses and performing the calculations via Octave, for the raw extracted data (converted and resampled signals from collected raw data) we have:

Signal 1: Rise time = 0.827 ms and Signal 2: Rise time = 0.832 ms. For the data extracted from the oscilloscope (normalized filtered entry signals) we have: Signal 1: Rise time = 0.838 ms and Signal 2: Rise time = 0.839 ms. The percentage error between the rise times calculated from the raw data and the oscilloscope data is approximately 1.3% for Signal 1 and 0.8% for Signal 2.

For the delay calculation, the threshold crossing method was performed at 50% of the signal amplitude, ensuring consistent and accurate estimation of the relative timing between the two signals.

Normalized signals - Lag time analysis

Extracting the points where the dashed line crosses and performing the calculations via Octave the following values are obtained for the raw extracted data delay = 1.9802 ms. For the data extracted from the oscilloscope we have delay = 2.0052 ms. The percentage error between these two delay measurements is approximately 1.25%.

For a period of 20 ms, these delays correspond to phase shifts of approximately 35.64° (raw data) and 36.47° (oscilloscope data). The percentage error between these phase shift values is approximately 1.25%.


8.1.3. Conclusions - Phase (or delay) and Rise time measurements

For phase and rise time measurements, also following the recommendations, successful data acquisition was achieved. The post-processing methodology and verification methods provide a means to directly compare ADC measurements with a trusted reference instrument (oscilloscope), identify and minimize errors caused by noise and signal amplitude variations through normalization and threshold crossing at 50% of rise time, validate the ADC’s capability to accurately capture phase shift (in our case, the lag time) and rise time consistently, and ensure that the digital acquisition system reliably reflects the temporal characteristics of the analog input signals.

By combining experimental verification with a clear and robust signal processing technique, this approach delivers confidence and precision in phase measurement using the STM32 ADC.

9. Conclusion

This wiki has provided a comprehensive guide to understanding and configuring the ADC peripheral on STM32 microcontrollers for various measurement types. By detailing key ADC parameters, ADC features, post-processing techniques, and evaluation methods, it offers a solid foundation for achieving accurate and reliable analog-to-digital conversions.

The practical examples and tailored recommendations for DC voltage, AC voltage, rise time, and phase measurements demonstrate how to apply these concepts effectively in real-world applications. Following these guidelines will help users optimize ADC performance, minimize errors, and enhance signal quality.

We encourage users to leverage this resource as a reference throughout their development process, adapting the recommendations to their specific application requirements. Continuous experimentation and validation remain essential to fully exploit the capabilities of the STM32 ADC and achieve optimal measurement results.


10. References