Microcontroller Interfacing Tutorials

Learn it by examples

By David Kebo Houngninou

On this page, you will find some interfacing experiments using the ARM Cortex MCBSTM32C.
- 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.

pic

MCBSTM32C board components

pic

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 depend 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 followings 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.

pic

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.

pic

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, lets 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 undertand what a GPIO is.

pic

Basic structure of a standard I/O port bit

What is a GPIO ?

The STM32F107VC has 7 general purpose input/output (GPIO) ports named Port A, B, C, D, E, F and G.
Each port can have up to 16 pins, and the following set of registers:

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.

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

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        */

Lets 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 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 )

pic

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

pic

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

pic

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

Setup and initialize the ADC converter

The Analog to Digital Converter (ADC) converts an analog input to a digital input for use by the microprocessor and the Digital to Analog (DAC) takes the microprocessor's digital output and converts it to an analog signal.

pic

ADC to STM32F107VC to DAC

We already enabled the APB2 clock now we enable the clock for the ADC.

RCC->APB2ENR |=  1 <<  9;             /* Enable ADC1 clock                  */
pic

APB2 peripheral clock enable register (RCC_APB2ENR)

GPIOC->CRL   &= 0xFFF0FFFF;           /* Configure PC4 as ADC.14 input      */

The potentiometer on the MCBSTM32C board connects to port pin PC4 (ADC12_IN14).
To use the potentiometer, pins must be configured as an analog input. By reading again Table 3 on the port bit configuration, you see that CNF4 and MODE4 must all be set to 0.
The line of code above is the same as:

GPIOC->CRL   = GPIOC->CRL & 0xFFF0FFFF;

So to configure PC4 we use the following mask:

1111 1111 1111 0000 1111 1111 1111 1111

The bitwise AND of the GPIOC->CRL register content with the mask above will clear bits CNF4 and MODE4.

pic

The potentiometer

1
2
3
ADC1->SQR1    = 0x00000000;           /* Regular channel 1 conversion       */
ADC1->SQR2    = 0x00000000;           /* Clear register                     */
ADC1->SQR3    = 14 <<  0;             /* SQ1 = channel 14                   */

Reading ADC values

Blinking the LEDs

Other project files

The following source files are required for the project.

  • STM32F10x.c contains the CPU startup
    code for the STMicroelectronics STM32F10x devices.
  • IRQ.c contains the target-dependent
    interrupt functions for the Timer and A/D converter.
  • Retarget.c configures the
    target-dependent low level functions for character I/O.
  • Setup.c and Blinky.c contain
    the application modules that monitors analog input, provides the
    text output, and toggles the LEDs.
  • STM32F10xR.LIB, contains the ST
    Software Library functions.
  • LCD_4bit.c, contains the functions
    to produce text for the LCD display.
  • Serial.c, contains the functions to
    communicate to the serial port.

Tutorial 2: Interfacing with the LCD

This tutorial will write and explain a small sample program that interfaces with the LCDs on the evaluation board.