Over 10 years we help companies reach their financial and branding goals. Engitech is a values-driven technology agency dedicated.



411 University St, Seattle, USA


+1 -800-456-478-23

Embedded MCU's Getting Started and Peripheral Coding STM32 MCU's STM32F1

STM32F103 & ADC: Single Channel Conversion

In the last post, we have gotten to know about the features of ADC Peripheral that we have in STM32 MCU. Now in this blog with the series of bare Metal Programming for Blue Pill, we will understand different register bytes and bits of ADC Peripheral to be used for using it in different features, configurations, and modes as we get to know about in the Previous Post.

In this blog, we will be going through how to use  ADC Peripheral for converting a Single Channel of ADC (only one ADC pin) and see its bare metal code.

Single  Channel Conversion  Mode: Only one ADC pin is used, this mode is like when we have say connected only one analog sensor to one of the ADC pins of MCU  like the Potentiometer is connected at PA0 pin.

ADC Registers In depth for:

Let\’s get into an in-depth understanding of which registers and their bits are used for configuring the ADC peripheral of Blue Pill in Single Channel Configuration. We will focus on bits and will give an explanation of why those bits are used for the

1.   ADC_SR(ADC status Register) –>This register tells the status of ADC channel  Conversion, as it name says.
STM32F103 ADC Status Register: 11.12.1
  • Bit 1[EOC ]: This bit is set by hardware when a single channel of any group (Regular or Injected) is converted successfully. So this bit is used for monitoring when the ADC conversion is completed by using it inside the while loop if interrupts are disabled.
0: ADC Channel Conversion is not completed

1: ADC Channel Conversion is completed

When hardware set this bit, we can clear this bit from the firmware end by setting the bit to 0 or by reading ADC_DR(ADC Data Register)

  • Bit 4[STRT]: This bit is set by hardware when regular channel conversion has begun. So when we start the Regular Channel Conversion, we will use this bit inside the while loop to check that whether Regular Channel conversion has started or not.
0: No regular Channel Conversion has started

1: Regular Channel Conversion has started

When hardware sets this bit, we can clear this bit from the firmware end by setting the bit to 0. Even if we don\’t clear this bit it will cause no effect during ADC Conversion. But its good practise to clear all bits of Status Register before starting the new conversion

2.            ADC_DR(ADC Data Register) –> This register stores the converted digital data at a 12-bit resolution of the converted ADC channel.
STM32F103 ADC Data Register 11.12.14
  • Bit 15:0 [DATA 15:0]: The ADC_DR is divided into two 16 bits groups. The first 16 bits from 0-15 contain the Converted value of the configured ADC Regular Channel.
As our ADC is of 12-bit resolution, so this is left aligned or right aligned to 4 bits so as to get the 12 ADC converted data .
Left Aligned or Right alignment of ADC Data Depends on ALIGN bit of ADC_CR2

So we will have following code and algorithm for ADC_SR & ADC_DR register:while(!(ADC1->SR & ADC_SR_STRT))

while(!(ADC1->SR & ADC_SR_EOC)); // wait till a group channel converstion has completed

adc_data = ADC1->DR; //clear the EOC bit by reading DR register


     3.      ADC_CR1(ADC Configuration register 1) –> This register is used for the  Configuration of ADC peripheral for
  • Analog Watchdog
  • Discontinuous Mode
  • Interrupt Enable/disable
  • Dual Mode configuration
  • Scan Mode 

As we are not using any of these features, so all the bits for these registers will be set to zero, and to know about these features and their bit functions, u can navigate to corresponding blogs for those.

STM32F103 ADC Configuration Register 1. 11.12.2
  • Bits 19:16 [DUALMODE 3:0]:  These bits are used to configure the type of operating mode. In the blue pill, we have two ADC peripherals: ADC1 & ADC2. We can use these  2 ADC peripherals simultaneously by configuring the respective ADC in different modes or in independent modes. We are going to use these ADC in independent mode as will be using only ADC1 peripheral, so DUALMODE[3:0] will be set to 0.
  • Bit 8[SCAN]: This bit is used to enable/disable the SCAN Mode feature in the ADC peripheral of BLUEPILL. Scan Mode is used when we convert more than 1 channel to scan all the configured channels in a Regular Group. As we are using only a single channel, means only one ADC pin is used so SCAN mode is not used and this bit will be set to 0.
0: Scan Mode disabled.

1:Scan Mode Enabled.

So we will have following code and algorith for ADC_CR1 register:ADC1->CR1 &= ~(ADC_CR1_SCAN); // SCAN DISABLED, if using scan mode then dma must be enabled

ADC1->CR1 &= ~(ADC_CR1_JDISCEN | ADC_CR1_DISCEN); // Discontinous mode disabled for both injected and regular groups

ADC1->CR1 &= ~(ADC_CR1_DISCNUM_2 | ADC_CR1_DISCNUM_1 | ADC_CR1_DISCNUM_2 ); // no channels are configured in discontinous way. // if discontinous mode is enabled then number of

//conversions to be done by discontinous mode has to be configured

// DISNUM bits


ADC1->CR1 &= ~(ADC_CR1_AWDEN | ADC_CR1_JAWDEN); // Analog watchdog disabled for both groups: regular and ibnjected

4. ADC_CR2(ADC Configuration Register 2) –> This register is used for the configuration of  ADC Peripheral for: 
  • ADC Conversion enables/disabled for regular and injected groups and ADC peripheral enable/disable.
  • Trigger source configuration for regular and injected groups.
  • ADC Data Alignment, DMA, Continous, temperature sensor setting.
STM32F103 ADC Configuration Register 2 11.12.3
  • Bit 0 [ADON]: ADC Peripheral On/OFF. This bit will be set to 1 to enable the ADC peripheral.  All channel configurations and ADC Peripheral configurations have to be made before setting this bit to 1.
0: Disable ADC Peripheral

1: Enable ADC Peripheral

  • Bit 1 [CONT]: This bit configures between Single Conversion mode and Continous Conversion mode. Continuous Conversion mode is selected when we have more than 1 ADC channel to be converted. As in this blog, we have Single Channel, so a Single Conversion mode will be used.
0: Single Conversion Mode

1: Continous Conversion Mode.

  • Bit 8[DMA]: This bit is used for Enabling DMA with ADC. DMA will be used when we are using Scan Conversation mode. This bit will be set to 0, as for the objective of this blog SCAN Mode is not used
0: DMA Disabled

1: DMA Enabled

  • Bit 11[ALIGN]: This bit is used for the Alignment of ADC_DR. We will be using the Right Alignmnet of ADC data Register
0: Right Alignment

1: Left Alignment

  • Bit 19:17[EXTSEL 2:0]: External event selection for ADC channels of regular group.  We will be using SW START event for starting ADC Conversion, thus these bits will be set to 0.


  • Bit 20[EXTTRIG]: This bit is used for enabling/disabling the External Event trigger to start ADC conversion on Regular Group.
0: Conversion on external event disabled

1: Conversion on internal event disabled

  • Bit 22[SWSTART]: This bit is the trigger source to start ADC conversion of the regular group if  SWSTART is
    selected as trigger event by the EXTSEL[2:0] bits.
0: Reset state

1: Start Regular group conversion

So we will have the following code and algorithm for the ADC_CR2 register:

ADC1->CR2&= ~ADC_CR2_ALIGN; // RIGHT aligned selected TP BE CHECK
ADC1->CR2|= (ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2); //Externel Triger source for Regular group
ADC1->CR2&= ~ADC_CR2_CONT; // Single conversion mode selected, CONTINOUS MODE DISABLED if : CONT = 1 Continous conversion mode will be selected

ADC1->CR2|= ADC_CR2_ADON; //ADC Enabled, before enabling should check that adc is disabled.

ADC1->CR2|= ADC_CR2_EXTTRIG; // externel event trigger for conversion is enabled , always enabled
ADC1->CR2|= ADC_CR2_SWSTART; // Start ADC Conversion of regular group




Leave a comment

Stay Updated With Us