How to use ADC in STM32F103C8 - Measuring Analog Voltage

Published  August 29, 2018   0
How to use ADC in STM32F103C8 - Measuring Analog Voltage using STM32 ADC

One common feature that is used in almost every embedded application is the ADC module (Analog to Digital Converter). These Analog to digital Converters can read voltage from analog sensors like Temperature sensor, Tilt sensor, Current sensor, Flex sensor and much more. So in this tutorial we will learn how to use ADC in STM32F103C8 to read Analog voltages using the Energia IDE. We will interface a small potentiometer to STM32 Blue Pill board and supply a varying voltage to an Analog pin, read the voltage and display it on the 16x2 LCD screen.

 

Comparing ADC in Arduino and STM32F103C8

In Arduino board, it contains a 6 channel (8 channels on the Mini and Nano, 16 on the Mega), 10-bit ADC with an input voltage range of 0V–5V. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023. Now in the case of STM32F103C8 we have 10 channels, 12-Bit ADC with an input range 0V -3.3V. It will map input voltages between 0 and 3.3 volts into integer values between 0 and 4095.

 

ADC in STM32

The ADC embedded in STM32 microcontrollers uses the SAR (successive approximation register) principle, by which the conversion is performed in several steps. The number of conversion steps is equal to the number of bits in the ADC converter. Each step is driven by the ADC clock. Each ADC clock produces one bit from result to output. The ADC internal design is based on the switched-capacitor technique. If you are new to STM32, then checkout our Getting started with STM32 tutorial.

 

12-bit Resolution

This ADC is a 10 channel 12 -bit ADC. Here the term 10 channel implies that there are 10 ADC pins using which we can measure analog voltage. The term 12-bit implies the resolution of the ADC. 12-bit means 2 to the power of ten (212) which is 4096. This is the number of sample steps for our ADC, so the range of our ADC values will be from 0 to 4095. The value will increase from 0 to 4095 based on the value of voltage per step, which can be calculated by formula

VOLTAGE / STEP = REFERENCE VOLTAGE / 4096 = (3.3/4096= 8.056mV) per unit.

 

How an Analog Signal is converted into Digital Format

As computers store and process only binary/digital values (1’s and 0’s).  So Analog signals like sensor’s output in volts has to be converted into digital values for processing and the conversion needs to be accurate .When a input analog voltage is given to STM32 at its Analog inputs, the analog value is read and stored in a integer variable. That stored Analog value(0-3.3V )  is converted into integers values (0-4096) using the formula below:

INPUT VOLTAGE = (ADC Value / ADC Resolution) * Reference Voltage

Resolution = 4096

Reference = 3.3V

 

ADC Pins in STM32F103C8T6

 

There are 10 Analog Pins in STM32 from PA0 to PB1.

Also check how to use ADC in other Microcontrollers:

 

Components Required

  • STM32F103C8
  • LCD 16*2
  • Potentiometer 100k
  • Breadboard
  • Connecting wires

 

Circuit Diagram and Explanations

The circuit diagram to interface 16*2 LCD and Analog Input to a STM32F103C8T6 board is shown below.

Circuit Diagram for Interfacing 16x2 LCD and Analog Input to a STM32F103C8T6 

 

The connections which are done for LCD are given below:

LCD Pin No

LCD Pin Name

STM32 Pin Name

1

Ground (Gnd)

Ground (G)

2

VCC

5V

3

VEE

Pin from Centre of Potentiometer

4

Register Select (RS)

PB11

5

Read/Write (RW)

Ground (G)

6

Enable (EN)

PB10

7

Data Bit 0 (DB0)

No Connection (NC)

8

Data Bit 1 (DB1)

No Connection (NC)

9

Data Bit 2 (DB2)

No Connection (NC)

10

Data Bit 3 (DB3)

No Connection (NC)

11

Data Bit 4 (DB4)

PB0

12

Data Bit 5 (DB5)

PB1

13

Data Bit 6 (DB6)

PC13

14

Data Bit 7 (DB7)

PC14

15

LED Positive

5V

16

LED Negative

Ground (G)

The connections are made according to the above given table. There are two Potentiometers present in the circuit, first one is used for voltage divider which can be used to vary voltage and provide analog input to STM32. Left pin of this potentiometer gets input positive voltage from STM32 (3.3V) and right pin is connected to ground, centre pin of potentiometer is connected to analog input pin (PA7) of STM32. The other potentiometer is used to vary the contrast of the LCD display. The power source for STM32 is provided by means of USB power supply from a PC or Laptop.

Circuit Hardware for Interfacing 16x2 LCD and Analog Input to a STM32F103C8T6

 

Programming STM32 for reading ADC values

In our previous tutorial, we learned about Programming STM32F103C8T6 Board using USB Port . So we don’t need a FTDI programmer now. Simply connect it to PC via USB port of STM32 and start programming with ARDUINO IDE. Programming your STM32 in ARDUINO IDE to read analog voltage is very simple. It is same like arduino board. There is no need of changing the jumper pins of STM32.

In this program will read the analog value and calculate the voltage with that value and then display both, analog and digital values, on the LCD screen.

 

First define out LCD pins. These define to which pin of STM32 the LCD pins are connected. You can modify as per your requirements.

const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to

 

Next, we include the header file for the LCD display. This calls the library which contains the code for how the STM32 should communicate with the LCD. Also make sure the function Liquid Crystal is called with the pin names that we just defined above.

#include <LiquidCrystal.h> // include the LCD library
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD

 

Inside the setup() function, we would just give an intro message to be displayed in the LCD screen. You can learn about interfacing LCD with STM32.

lcd.begin(16, 2); //We are using a 16*2 LCD
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0); //At first row first column 
lcd.print("CIRCUITDIGEST"); //Print this
lcd.setCursor(0, 1); //At secound row first column
lcd.print("STM32F103C8"); //Print this
delay(2000); //wait for two secounds 
lcd.clear(); //Clear the screen
lcd.setCursor(0, 0);  //At first row first column
lcd.print("USING ADC IN");//Print this
lcd.setCursor(0,1); //At secound row first column 
lcd.print("STM32F103C8");//Print this
delay(2000); //wait for two secounds 
lcd.clear(); //Clear the screen

 

Finally, inside our infinite loop() function, we start reading the analog voltage supplied to the PA7 pin from potentiometer. As we discussed already, the microcontroller is a digital device and it cannot read voltages level directly. Using SAR technique the voltage level is mapped from 0 to 4096. These values are called the ADC values, to get this ADC value simply use the following line

int val = analogRead(A7);    // read the ADC value from pin PA7

 

Here the function analogRead() is used to read the analog value of the pin. Finally we save this value in a variable called “val”. The type of this variable is integer because we will only get values ranging from 0 to 4096 to be stored in this variable.

 

The next step would be to calculate the voltage value from the ADC value. To do this we have the following formulae

Voltage = (ADC Value / ADC Resolution) * Reference Voltage

 

In our case we already know that the ADC resolution of our microcontroller is 4096. The ADC value is also found in the previous line and stored the variable called val. The reference voltage is equal to the voltage at which the microcontroller is operating. When the STM32 board is powered via USB cable then the operating voltage is 3.3V. You can also measure the operating voltage by using a multimeter across the Vcc and ground pin on the board. So the above formula fits into our case as shown below

float voltage = (float(val)/4096) * 3.3; //formulae to convert the ADC value to voltage

 

 

You might be confused with the line float (val). This is used to convert the variable “val” from int data type to “float” data type. This conversion is needed because only if we get the result of val/4096 in float we can multiply it 3.3. If the value is received in integer it will always be 0 and the result will also be zero. Once we have calculated the ADC value and voltage, all that is left is to display the result on the LCD screen which can be done by using the following lines

  lcd.setCursor(0, 0);   // set the cursor to column 0, line 0
  lcd.print("ADC Val:");
  lcd.print(val); //Display ADC value
  lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print("Voltage:");
  lcd.print(voltage); //Display voltage

 

Complete code and Demonstration Video is given below.

Code

#include <LiquidCrystal.h> // include the LCD library
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to 
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD
const int analogip = PA7;//Initialize the analog input pin
void setup() 
{
  lcd.begin(16, 2); //We are using a 16*2 LCD
  lcd.clear(); //Clear the screen
  lcd.setCursor(0, 0); //At first row first column 
  lcd.print("CIRCUITDIGEST"); //Print this
  lcd.setCursor(0, 1); //At secound row first column 
  lcd.print("STM32F103C8"); //Print this
  delay(2000); //wait for two secounds 
  lcd.clear(); //Clear the screen
  lcd.setCursor(0, 0);  //At first row first column
  lcd.print("USING ADC IN");//Print this
  lcd.setCursor(0,1); //At secound row first column 
  lcd.print("STM32F103C8");//Print this
  delay(2000); //wait for two secounds 
  lcd.clear(); //Clear the screen
}
void loop()
{   
  int val = analogRead(PA7);    // read the ADC value from pin A7
  float voltage = (float(val)/4096) * 3.3; //formulae to convert the ADC value to voltage
  lcd.setCursor(0, 0);   // set the cursor to column 0, line 0
  lcd.print("ADC Val:");
  lcd.print(val); //Display ADC value
  lcd.setCursor(0, 1);   // set the cursor to column 0, line 1
  lcd.print("Voltage:");
  lcd.print(voltage); //Display voltage
}

 

Video

Have any question realated to this Article?

Ask Our Community Members