STM32F107VC Microcontroller Interfacing

Microcontroller Interfacing Tutorials

Learn it by examples

By David Kebo Houngninou

On this page, you will find some interfacing experiments using the ARM Cortex M3.
– The evaluation board we target is the MCBSTM32C running on the STM32F107VC microcontroller.
– The tutorial focuses on configuring the MCBSTM32C and interfacing.
– Datasheets and documentation for STMicroelectronics STM32F107VC core is available at: http://www.keil.com/dd/chip/4889.htm.
– The reference used for this tutorial is the RM0008 Reference manual for STM32F107xx advanced ARM®-based 32-bit MCUs.

Table of contents

What is a microcontroller?

A microcontroller is a self-contained system with peripherals, memory, and a processor that can be used as an embedded system.

Overview of the MCBSTM32C board evaluation board

The MCBSTM32C Evaluation Board ships with the STM32F107VC core.

MCBSTM32C board components

MCBSTM32C interfacing features

Tutorial 1: Interfacing with the LEDs

This tutorial will explain how a program that interfaces with the LEDs on the evaluation board works.
The BLINKY example program toggles the LEDs on GPIO1 and prints the converted A-to-D value to the serial port.
The toggle speed of the LEDs depends on the input voltage of the ADC1 input.
The BLINKY program demonstrates assembling, linking, and debugging using the µVision IDE on the MCBSTM32 board.
The on-board LEDs make it easy to visually verify that the program loads and executes properly.
The HyperTerm terminal emulator program makes it easy to verify serial output.

The tutorial will cover the following topics:

  • Hardware and software requirements
  • Writing the main program
  • Explaining the configuration (Ports, registers, pins, etc.)
  • How to debug the program?
  • How to check the serial output?
  • Other project files

Hardware and software requirements

To run this experiment you need the following:

  • The MCBSTM32 Evaluation Board
  • A ULINK-ME debug adapter for downloading and debugging
  • 2 USB cables (One for power and one for debugging)
  • The MDK-ARM development environment for Cortex and ARM devices.

You can download the full tutorial program here: BLINKY Tutorial

Writing the main program

This program uses the potentiometer and the LEDs on the board, it blinks the 8 LEDs in a cyclic manner depending on the potentiometer position.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/******************************************************************************/
/* BLINKY.C: LED Flasher                                                      */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2005-2009 Keil Software. All rights reserved.                */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/

#include <stm32f10x_cl.h>

#define LED_NUM     8                   /* Number of user LEDs                */

const long led_mask[] = { 1<<15, 1<<14, 1<<13, 1<<12, 1<<11, 1<<10, 1<<9, 1<<8 };


int main (void) {
  int AD_val, i;
  int num = -1; 
  int dir =  1;

  SystemInit();

  /* Setup GPIO for LEDs                                                      */
  RCC->APB2ENR |=  1 <<  6;             /* Enable GPIOE clock                 */
  GPIOE->CRH    = 0x33333333;           /* Configure the GPIO for LEDs        */

  /* Setup and initialize ADC converter                                       */
  RCC->APB2ENR |=  1 <<  9;             /* Enable ADC1 clock                  */
  GPIOC->CRL   &= 0xFFF0FFFF;           /* Configure PC4 as ADC.14 input      */
  ADC1->SQR1    = 0x00000000;           /* Regular channel 1 conversion       */
  ADC1->SQR2    = 0x00000000;           /* Clear register                     */
  ADC1->SQR3    = 14 <<  0;             /* SQ1 = channel 14                   */
  ADC1->SMPR1   =  5 << 12;             /* Channel 14 sample time is 55.5 cyc */
  ADC1->SMPR2   = 0x00000000;           /* Clear register                     */
  ADC1->CR1     =  1 <<  8;             /* Scan mode on                       */
  ADC1->CR2     = (1 << 20) |           /* Enable external trigger            */
                  (7 << 17) |           /* EXTSEL = SWSTART                   */
                  (1 <<  1) |           /* Continuous conversion              */
                  (1 <<  0) ;           /* ADC enable                         */
  ADC1->CR2    |=  1 <<  3;             /* Initialize calibration registers   */
  while (ADC1->CR2 & (1 << 3));         /* Wait for initialization to finish  */
  ADC1->CR2    |=  1 <<  2;             /* Start calibration                  */
  while (ADC1->CR2 & (1 << 2));         /* Wait for calibration to finish     */
  ADC1->CR2    |=  1 << 22;             /* Start first conversion             */ 

  for (;;) {                            /* Loop forever                       */
    if (ADC1->SR & (1 << 1)) {          /* If conversion has finished         */
      AD_val = ADC1->DR & 0x0FFF;       /* Read AD converted value            */
      ADC1->CR2 |= 1 << 22;             /* Start new conversion               */ 
    }

    /* Calculate 'num': 0, 1, ... , LED_NUM-1, LED_NUM-1, ... , 1, 0, 0, ...  */
    num += dir;
    if (num >= LED_NUM) { dir = -1; num = LED_NUM-1; } 
    else if   (num < 0) { dir =  1; num = 0;         }

    GPIOE->BSRR = led_mask[num];        /* Turn LED on                        */
    for (i = 0; i < ((AD_val << 8) + 100000); i++);
    GPIOE->BSRR = led_mask[num] << 16;  /* Turn LED off                       */
  }
}

The main program consists of 6 main parts

  1. Initialize the microcontroller
  2. Enable the clock
  3. Setup the GPIO for the LEDs
  4. Setup and initialize the ADC
  5. Read the ADC values
  6. Blink the LEDs

We will go over each of these parts and include some code snippets of Blinky.c to explain the configuration

Initialize the microcontroller

SystemInit() is a function defined in the source file system_stm32f10x_cl.c
It initializes the embedded flash interface, and update the system clock frequency.

Enable the clock

In order to conserve power, the ARM microcontroller does not hold the clock active continuously.
It is the responsibility of the programmer to enable the clock for each peripheral.
We have to manually enable the clock for the peripherals that we need to use.
To enable the GPIO, we must set the appropriate bit(s) in the register RCC_APB2ENR.

APB2 peripheral clock enable register (RCC_APB2ENR)

On the Keil MCBSTM32C board, the 8 Port LEDs marked PE.8 – PE.15 connect to port E.

The 8 Port LEDs marked PE.8 – PE.15

To enable port E, clock bit 6 of the register APB2ENR must be set.

RCC->APB2ENR |=  1 <<  6;             /* Enable GPIOE clock                 */

The line of code above is the same as:

RCC->APB2ENR = RCC->APB2ENR | 1 << 6;

The sign “<<“ is called a bit left-shift operation and this is why:
Integers are stored, in memory, as a series of bits. For example, the number 1 stored as a 32-bit int would be:

00000000 00000000 00000000 00000001

Shifting this bit pattern to the left by six positions (1 << 6) would result in the number 64:

00000000 00000000 00000000 1000000

As you can see, the digits have shifted to the left by six positions, and the digits on the right is filled with a zero.
You might also note that shifting left is equivalent to multiplication by powers of 2. So 1 << 6 is equivalent to 2^6.
The sign “|=” is called a bitwise OR operation
First, let’s take a look at the truth table of a logic OR:

x1 x2 f
0 0 0
0 1 1
1 0 1
1 1 1

The truth table for a logic OR (|)

If a least one of the inputs is set to 1, then the output is set to 1
This is an interesting property to use to set specific bits in a register
By performing a bitwise OR of RCC->APB2ENR by 1 << 6 we set the 6th clock bit of RCC->APB2ENR to 1 and we keep all the other bits unchanged

Setup the GPIO for LEDs

After enabling the clock the next step in using the general-purpose input-output port (GPIO) is to configure it for its desired application.
Before getting into configuration details, we need to understand what a GPIO is.

Basic structure of a standard I/O port bit

What is a GPIO port?

A GPIO port is a group of user-configurable pins for General Purpose Input/Output

  • The STM32F107VC has 7 general purpose input/output (GPIO) ports
  • The 7 GPIO Ports are A, B, C, D, E, F, and G.
  • Each GPIO port can have up to 16 pins
  • Each GPIO port has 7 registers

The 7 GPIO Ports are A, B, C, D, E, F, and G on STM32F107 microcontroller

What is a GPIO pin?

A GPIO pin is a generic pin controllable by the user at run time and configurable to be input or output.

GPIO pin

What is a GPIO register?

A GPIO register is a 32-bit storage area that holds configuration bits for a GPIO pin

Example of a configurable 32-bit register

Each of the general purpose I/O ports has a:

  • 32-bit configuration register low GPIOx_CRL
  • 32-bit configuration register high GPIOx_CRH
  • 32-bit input data register GPIOx_IDR
  • 32-bit output data register GPIOx_ODR
  • 32-bit set/reset register GPIOx_BSRR
  • 16-bit reset register GPIOx_BRR
  • 32-bit locking register GPIOx_LCKR

where the ‘x’ in each register name acronym represents the port name.
e.g. GPIOA_IDR is the input data register associated with port A.
(Reference: RM0008 Reference manual Page 170)

To configure the STM32F107 microcontroller we perform the following steps:

  • Enable the clock to the appropriate GPIO
  • Configure the output pin(s) to give the desired function
  • Lock the configuration

Setup for Interfacing with the LEDs

  1. Initialize the microcontroller
  2. Enable the clock for the LEDs
  3. Setup the GPIO for the LEDs
  4. Setup and initialize the ADC
  5. Read the ADC values
  6. Blink the LEDs

Initialize the microcontroller

SystemInit() is a function defined in the source file system_stm32f10x_cl.c The purpose of this function is to:
Initialize the embedded flash interface
Update the system clock frequency

Enable the clock for the LEDs

The ARM microcontroller does not hold the clock active continuously

  • Enable the clock for the LEDs manually (Port E)
  • Set configuration bit(s) in register RCC_APB2ENR
  • RCC_APB2ENR: Advanced Peripheral Bus 2 Enable Register

Enable the clock for the LEDs

Setup the GPIO for the LEDs

  • LEDs pins are wired to GPIOE (Port E)
  • The 16 pins are PE0 to PE15
  • LEDs are wired to pins PE8,…PE15
  • Configure the pins as output
  • GPIOE->CRH = 0x33333333;

Setup the GPIO for the LEDs

For each pin there is a bit in a register that can be set to configure the pin as an output.
The MCBSTM32C has LEDs wired to pins 8 through 15 of GPIOE.

GPIOE->CRH    = 0x33333333;           /* Configure the GPIO for LEDs        */

Let’s explain what this line of code is doing:
First, we enable the clock to GPIOE and configure pins 8 through 15 as outputs.
By looking at table Table 2, we see that GPIOE_CRH (Control Register High) controls bits 8 through 15.
To configure GPIOE_CRH as a push-pull output we need to use the patterns CNFx[1:0] = 00 and MODEx[1:0] = 01,10 or 11 (See Table 3)
We can use the following pattern:

0011 0011 0011 0011 0011 0011 0011 0011

So the register content is:

GPIOE->CRH = 0x33333333;     	//Configure the GPIO for LEDs

The table below summarizes how GPIOx_CRH and GPIOx_CRL are connected to the 16 pins of a port
Each pin requires 4 bits to configure 2 bits for CNFx and 2 bits for MODEx

Name r/w Bits Function
GPIOx_CRL Port configuration register low rw CNF[1:0], MODE[1:0] Configure lowest 8 bit of port x. IN or OUT
GPIOx_CRH Port configuration register high rw CNF[1:0], MODE[1:0] Configure highest 8 bit of port x. IN or OUT
GPIOx_IDR port input data register r IDR[15:0] Read state of pins configured for input on port x (Lowest 16 bits of word)
GPIOx_ODR port output data register rw ODR[15:0] Write to pins configured for Output on port x (Lowest 16 bits of word)
GPIOx_BSRR Port bit set/reset register w BS[15:0], BR[15:0] Atomic Set/Reset individual Pins configured for Output.
GPIOx_BRR Port bit reset register w BR[15:0] Atomic Reset individual Pins configured for Output. (Lowest 16 bits of word)
GPIOx_LCKR Port configuration lock register rw LCK[15:0], LCKK Lock individual pins of port x (Freeze CRL and CRH of ports)

Table 2: GPIO Configuration Registers. (Note:x = Port A to G )

Port configuration register low (GPIOx_CRL) (x=A..G)

Port configuration register high (GPIOx_CRH) (x=A..G)

Port configuration register to pins

Configuration mode CNF1 CNF0 MODE1 MODE0 PxODR register
General Purpose Output Push-Pull 0 0 01
10
11
See Mode below
0 or 1
Open Drain 1 0 or 1
Alternate function Output Push-Pull 1 0 Don’t Care
Open Drain 1 Don’t Care
Input Analog 0 0 00 Don’t Care
Input Floating 1 Don’t Care
Input Pull-Down 1 0 0
Input Pull-Up 1

Table 3: Port bit configuration summary

MODE[1:0] Meaning
00 Reserved
01 Max. output speed 10 MHz
10 Max. output speed 2 MHz
11 Max. output speed 50 MHz

Table 4: MODE[1:0] configuration bits

Tutorial 2: Setup and initialize the ADC

This tutorial will explain how to configure the Analog to Digital converter on the evaluation button

Tutorial 2 >>

Tutorial 3: Blinking the LEDs

Tutorial 3 >>

Tutorial 4: Timers

Tutorial 4 >>

Scroll to Top