Stm32 Baremetal Embedded-C Programming

ADC configuration in continuous mode for STM32

Interfacing ADC in ARM Cortex M3 controller in continuous mode

Rohit Nimkar
5 min readFeb 19, 2023

In the STM32F103 board, we have a single Successive Approximation type Analog to Digital Converter with a resolution of 12 bits. It has 18 channels which allow us to measure analog voltage from 16 external and 2 internal sources.

The A/D conversion of all channels can be performed in continuous, discontinuous, scan, and single modes. The result can be stored in the data register in both the left and right alignments.

The ADC input clock is generated by PCLK2 divided by a pre scalar and it must not exceed 14 MHz

fig: Control flow diagram

Functional Description

The ADC can be switched on/off by setting the ADON bit in the CR2 register. When the ADON bit is set for the first time i.e. value changes from 0 to 1, the ADC wakes up from power-down mode. The conversion starts when the ADON bit is set for the second time after the ADC power-up time.

The temperature sensor is connected to channel ADCx_IN16 and the internal reference voltage VREFINT is connected to ADCx_IN17. These two internal channels can be selected and converted as injected or regular channels.

Modes

The ADC can be operated in any one of the following modes. In this article, we are going to discuss the continuous operation mode.

Single Conversion Mode

In single conversion mode, the ADC stops after performing only one conversion. The mode can be started by either the external trigger or by setting the ADON bit while the CONT bit is 0.

Continuous Mode

In continuous conversion mode, the ADC starts the next conversion as soon as it finishes one. This mode can be triggered by either the external trigger or by setting the ADON bit while the CONT bit is 1.

After each conversion:
Data is stored in the 16-bit ADC_DR register and the End of Conversion (EOC) flag is set. An interrupt is generated if the EOCIE bit is set.

Scan Mode

Scan mode is used to scan a group of analog channels. This mode can be triggered by setting the SCAN bit in the ADC_CR1 register. The temperature sensor is connected to channel ADCx_IN16 and the internal reference voltage VREFINT is connected to ADCx_IN17. These two internal channels can be selected and converted as injected or regular channels.

Discontinuous Mode

This mode is enabled by setting the DISCEN bit in the ADC_CR1 register. It can convert a short sequence of n conversions (n <=8), a part of the sequence of conversions selected in the ADC_SQRx registers. The value of n is specified by writing to the DISCNUM[2:0] bits in the ADC_CR1 register.

Calibration

The ADC has a built-in self-calibration mode. Calibration significantly reduces accuracy errors due to internal capacitor bank variations. During calibration, an error correction code (digital word) is calculated for each capacitor, and during all subsequent conversions, the error contribution of each capacitor is removed using this code.

Calibration is started by setting the CAL bit in the ADC_CR2 register. Once calibration is over, the CAL bit is reset by the hardware and normal conversion can be performed. It is recommended to calibrate the ADC once at power-on. The calibration codes are stored in the ADC_DR as soon as the calibration phase ends.

It is recommended to perform a calibration after each power-up.

Before starting calibration, the ADC must have been in a power-on state (ADON bit = ‘1’) for at least two ADC clock cycles.

Data Alignment

ALIGN bit in the ADC_CR2 register selects the alignment of data stored after conversion. Data can be left or right-aligned as shown in fig

left data alignment
fig: left alignment
right data alignment
fig: right-alignment

Programmable Sample time

ADC samples the input voltage for a number of ADC_CLK cycles which can be modified using the SMP[2:0] bits in the ADC_SMPR1 and ADC_SMPR2 registers. Each channel can be sampled with a different sample time.

The total conversion time is calculated as follows:
Tconv = Sampling time + 12.5 cycles

Example:
With an ADCCLK = 14 MHz and a sampling time of 1.5 cycles: Tconv = 1.5 + 12.5 = 14 cycles = 1 μs

Program

The program initialization the peripherals and then continuously writes the analog reading on the serial console. The clock configuration and the ADC configuration are explained in detail however the USART functions are invoked from the library, explained in the following article

Clock initialization

By default, the controller is using the internal RC oscillator operating at 8MHz as the primary clock. We will be configuring it to use the external resonator as the clock source operating at 72MHz.

clock initialization

To dive deep into the inner working of the clock circuit and its configuration, head over to the following article:

ADC Config & Initialization

As the ADC clock cannot exceed 14MHz, we will select the pre-scalar value accordingly i.e. 6. ADC clock will have a frequency of 72Mhz/6 = 12MHz . The clock sources of ADC and PORTA are enabled afterward.

Pin PA0 where the analog sensor is connected is reset and configured in analog input mode.

For better accuracy, the sampling time is set as 28.5 cycles as described in the above section. The ADC is woken from the power down state while setting the mode as continuous and right data alignment. The ADC will keep reading the value and updating it in the ADC_DR register in right-aligned mode.

The conversions are started after the completion of recalibration.

ADC initialization

Main function

As the ADC is configured in continuous mode, the value read from the ADC_DR register is printed on the serial console at every 500ms interval.

Building & Flashing on target

This project is configured using Makefile and does not use any external libraries. The entire project is available in the following repository along with all the instructions for building & flashing.

References

  1. STM32F103 reference manual

--

--

Rohit Nimkar

Know a little about coding but aim to self employ myself from it.