Manual ARM Microcontroller Course E.T.S.V. Scintilla: Cursuscommissie May 27, 2015
Manual ARM Microcontroller Course E.T.S.V. Scintilla: Cursuscommissie May 27, 2015
Scintilla
Cursuscommissie
1
Contents
1 Introduction 4
1.1 Preliminary Schedule . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 Starting a Project 9
3.1 Clock Configuration . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Flashing the Program Memory . . . . . . . . . . . . . . . . . . . 9
3.2.1 STLink Utility under Windows . . . . . . . . . . . . . . . 9
3.2.2 STLink Flash under Linux . . . . . . . . . . . . . . . . . . 9
3.3 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4 Programming C 12
4.1 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.1.1 Integer Data types . . . . . . . . . . . . . . . . . . . . . . 12
4.1.2 Floating point data types . . . . . . . . . . . . . . . . . . 13
4.1.3 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1.4 Structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.1.5 Enumerated type . . . . . . . . . . . . . . . . . . . . . . . 15
4.2 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2.1 Standard Operators . . . . . . . . . . . . . . . . . . . . . 15
4.2.2 Logical Operators . . . . . . . . . . . . . . . . . . . . . . 15
4.2.3 Bitwise operators . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.4 Compound assignment operators . . . . . . . . . . . . . . 16
4.3 Statements in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.3.1 Conditional Statements . . . . . . . . . . . . . . . . . . . 18
4.3.2 Iteration Statements . . . . . . . . . . . . . . . . . . . . . 19
4.4 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5 Microcontroller Settings 21
5.1 Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
5.2 Libraries with “typedef”s . . . . . . . . . . . . . . . . . . . . . . . 21
7 GPIO 22
2
8 Polling and Interrupts 22
8.1 Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.2 Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.3 Polling vs. Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . 25
9 Timers 27
10 Analog Peripherals 30
11 SPI 32
11.1 Talking to the DAC . . . . . . . . . . . . . . . . . . . . . . . . . 32
13 Energy Consumption 33
3
1 Introduction
Welcome to the ARM microcontroller course 2015 of ETSV Scintilla. In this
course we hope to teach you some of the basics of programming a microcon-
troller, the common caveats and the fun of getting a mixed hardware and soft-
ware project to work. We’ve chosen for an ARM microcontroller as these are
more and more common, with a lot of chip manufacturers having their own im-
plementations. The goal is to build a function generator using a Nucleo-F411RE
board, made by ST, and a the shield. In order to build that, we’ll talk about
using digital input and outputs, analog peripherals, timers and SPI. Using that
and a little background information on Direct Digital Synthesis, you should be
able to have a function generator running on the last evening.
Day 4 Direct Digital Synthesis and building a function generator. Section 12.
1.2 Acknowledgments
We would like to thanks our sponsor ST Microelectronics for supplying the
Nucleo-F411RE development board, Eurocircuits for supplying the shield PCB
and Analog Devices for the DAC.
4
2 Setup Eclipse and Toolchain
In this course Eclipse is used as the IDE, as it’s cross-platform and highly
customizable. It is recommended to use a clean install of Eclipse 4.4 Luna for
C/C++. Besides Eclipse you’ll need to install some Eclipse plugins and drivers
for STLink, the device that connects to your Nucleo board. The guide is written
with Windows and GNU/Linux in mind, but it should work as well on OSX.
2.1 Windows
This guide assumes that you’ve a recent version of Java Runtime Environment
installed. If needed you can download JRE from http://www.oracle.com/
technetwork/java/javase/downloads/jre8-downloads-2133155.html.
2.1.1 Eclipse
1. Go to http://www.eclipse.org/downloads/ and download Eclipse
IDE for C/C++ Developers
2. Unpack and install.
2.1.2 Toolchain
1. Get the toolchain from https://launchpad.net/gcc-arm-embedded.
(gcc-arm-none-eabi***-win32.exe)1
2. Install the toolchain, but in the final window disable "Add path to the
environment variable".
5
2.1.3 STLink v2
1. Download the latest STLink v2 driver from http://www.st.com/web/
catalog/tools/FM147/SC1887/PF260218
2. Extract files and run stlink_winusb_install
3. Install driver.
4. Download STLink Utility from http://www.st.com/web/en/catalog/
tools/PF258168, install.
2.2 Linux
This guide assumes a working Java runtime environment. It was tested using
OpenJDK 1.8, and should work equally well with a recent version of Oracle
JRE.
downloads/
6
4. open Eclipse, set a workspace and click on Help → Install New software.
5. click on Add..., fill in Name: GNU ARM Eclipse Plug-ins. Location:
http://gnuarmeclipse.sourceforge.net/updates and press OK
6. select all but the Freescale Project Templates, click Next and install.
7. In Eclipse, go to Window → Preferences. C/C++ → Build → Global
Tools Paths
8. Select GNU Tools for ARM Embedded Processors, locate the toolchain
and enter the path in Toolchain folder.
1. Download the latest development (0.9.*) version of OpenOCD for your ar-
chitecture from http://sourceforge.net/projects/gnuarmeclipse/
files/OpenOCD/GNULinux/.
2. Extract the package to a directory.
3. In Eclipse go to Window → Preferences → Run/Debug → String Substi-
tutions
7
4. Fill in the path to the bin directory of OpenOCD in the Value field of
openocd_path, then click OK.
8
3 Starting a Project
To accompany this guide there is a video walk-through available on https:
//www.youtube.com/watch?v=HxGEBEWRyy8
In Eclipse go to File → New C Project. Enter a name for the project,
and select STM32F4xx C/C++ Project from the project type dropdown. From
Toolchains choose the Cross ARM GCC.
In the next menu, for the Nucleo-F411 in the Target processor needs to be
changed to Cortex-M4, the flash size to 512KB, and Content: Empty.
Keep the suggested settings in the Folders menu and Select Configurations menu.
In the Cross GNU ARM Toolchain make sure to select the Toolchain GNU
Tools for ARM Embedded Processors, and if necessary locate the bin
folder of the toolchain. Click Finish. Now a simple project is set up with an
empty main() function.
To make optimal use of our Eclipse installation, right-click on the project, and
select Properties. Browse to C/C++ Build → Settings → Devices. Locate
the STM32F411RE, select it and click Okay. You can now test the installation
by pressing the Build icon.
datasheet.
9
Snippet 1 84MHz system clock configuration for Nucleo-F411RE
/** System Clock Configuration
*/
void configure_system_clock(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|
RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
10
3. Now you can run st-flash by clicking Run → External Tools → stlinkv2
3.3 Debugging
This part assumes you installed OpenOCD, as in section 2.1.4 for Windows or
2.2.3 for GNU/Linux.
1. Build the project and make sure the executable file exist.
11
4 Programming C
Due to its low level description, C is a relatively simple language to get started
with: it features only a minimum of possible operations, so there is not that
much to learn.
12
Snippet 2 Example of an integer as a Boolean
uint16_t x = 1615;
if(x){
setLED();
}else{
resetLED();
}
Name Syntax Sign bit Exponent bits Fraction bits Size (bits)
4.1.3 Arrays
An array is an indexed lists of a certain data type. These arrays can e.g. be used
to store lists of variables, as we will do later to map an output sample number
to an output value. As in every properly thought out programming language,
the first entry in the array is numbered “0”. As an example, the example code
13
in code snippet 3 generates a list of squares of the first 8 integer numbers and
returns the value of the fifth square. This should be 25.
4.1.4 Structs
C is no object oriented language, but has a feature which comes close to object
oriented storing of variables. This can be done by defining a so called “struct”
type variable. A struct can be considered to be an object with several variables
in it. Structs are used often where there is a clear repetition in data sets. As an
example, a microcontroller has several sets of input and output pins (or “general
purpose input and output (GPIO) ports”, more about this later). Each GPIO
port has (amongst others) a setting for pin modes. Data could be organized in
a very convenient way if we could make an object “GPIO port” with as one of
its internal variables a value for the pin mode for that port. In code snippet
4 the type definition (similar to a class) for the GPIO ports is given, a struct
(similar to an object) “GPIOA” is created, and one of its variables is changed
and returned.
14
4.1.5 Enumerated type
An enumerated type is a limited list of keywords, using symbolic names to make
a program clearer to the programmer. This data type will be useful when you
want to implement a state machine, as in code snippet 5. The defined keywords
can be used directly in code.
4.2 Operators
To perform operations on variables, operators can be used. These operators can
be categorized into 4 main categories:
4. Bitwise operators
This section gives a brief overview of these operators.
15
Table 3 List of logical operators on words
a 1 1 0 0 → TRUE
b 0 1 1 0 → TRUE &&
return value: TRUE
16
Table 5 List of bitwise operators
a 1 1 0 0
b 0 1 1 0 &
return value: 0 1 0 0
Bit number 7 6 5 4 3 2 1 0
Current value of x 1 0 1 0 1 0 1 0
Desired value of x 1 0 0 0 1 0 1 0
17
4.3 Statements in C
To build logical blocks with these operators, statements are added to determine
when and how to perform the logical operations. This can be done using control
statements. This section will cover some basic control statements.
18
haveBreakfast();
//then continue with the next step of your morning
routine
case 1:
//leave directly if there is only on 1 quarter of an
hour left
leaveForLecture();
19
4.4 Functions
If code is to be used multiple places, it is advised to make functions of these
blocks of code. This manual assumes you know what functions are. The C
syntax for functions is as given in code snippet 12. Use a reference to the
function inside the main() scope and the code in the function block will be
executed. The declaration of a function needs to be before the first call of the
function. To do that you can use function prototypes, where you specify the
name, return type and number and types of the arguments.
int main(){
//define some variables
int16_t a = 4;
int16_t b = 5;
20
5 Microcontroller Settings
5.1 Registers
The memory of a microcontroller is divided into words of 32 bits. These are
called “registers”. These registers can contain e.g. the stored value of a variable
in your process. Apart from the memory for variables, there are also registers
which have special functions. The values in these registers are connected to
in hardware to specific blocks with specific functions, such as settings for a
hardware component. Writing to those special registers allow the user to change
the settings of the microcontroller.
21
Both these options can be configured in the system settings of an ARM. After a
reset or power down, the ARM reboots and sets a 16MHz internal RC oscillator
as system clock and disables all hardware peripherals. This means that to use
any subsystem of the chip, e.g. GPIO pins, DACs and timers, the clock to this
module has to be enabled first.
If clock frequencies higher than 16MHz are required (which it will be near the
end of the course), the internal phase locked loop (PLL) has to be used. This
PLL uses the 16MHz RC oscillator as an input and multiplies this frequency to
generate a high frequency clock. If this PLL output is then set to function as
the system clock, higher performance can achieved at the cost of a higher power
consumption.
7 GPIO
GPIO is an abbreviation for “General Purpose Input and Output” and allows
the programmer to read or set the voltages on the pins of the microcontroller
to a high (3.3V) or low (0V) value. In ARM microcontrollers, the input and
output pins can be read and written to similar to a memory address. Input
pins are connected to a (read only) input data register which can be read in the
same way any other register is read. Output pins are connected to an output
data register. This is a register just like any other, except this memory cell
is connected to pins, so the bits in this register determine the voltages on the
pins of the chip. This principle of interacting with GPIO pins in the same
way as with memory addresses is called “memory mapped input and output” or
“memory mapped IO”.
The GPIO pins are grouped in functional units called ports. The microcontroller
used for this course features six ports: port A, B, C, D, E and F. Each port
has multiple registers to change the settings for the pins in it. The rest of this
chapter will use a small x to indicate a register, this x can be replaced by the
letters A, B, C, D, E and F to function for this specific port. E.g. the mode
register (GPIOx_MODER) for port B is “GPIOB_MODER”. The registers
with the possible settings for GPIO pins are given in table 11.
Exercise 1
Turn on the LED on the Nucleo board. To do this follow the following steps:
1. Find out to which microcontroller pin the user LED is connected (refer to
chapter 5.4 and table 15 of the Nucleo user manual)
22
Table 9 List of possible GPIO settings in ARM microcontrollers
GPIOx_IDR 8.4.5 Input data register Allows to read the digital value
of an input pin
similar to e.g. a MATLAB calculation. This is what you have done in exercise
1. In virtually all practical cases a microcontroller executes a continuous task
and is never finished with its program. This leaves us the other two options.
8.1 Polling
A way to program a microcontroller program to run until the end of times is
with the use of a while(1){} loop. As the argument for the loop will be true
forever, the microcontroller will loop the code within the braces forever. Your
code can now be split up in two parts: first an initialization to be performed
once, followed by a loop with the code which should be run continuously. An
example project which turns on an LED when a button is pressed could be
as in code example 13. Keep in mind that this example refers to a library
(buttonLED.h) to call functions from, so this example code alone is not enough
to switch the LED on and off. This approach, the microcontroller will check the
state of the button every time the loop is performed. Processes in which the
processor checks for input, such as the LED example in code example 13 are
called “polling”. Polling is easy to implement and gives programmer complete
control over the order of the performed instructions, but it does have some
downsides.
23
Snippet 13 Example of using a while(1) loop and polling
//include a libraries here
#include buttonLED.h
int main(){
//run the initialization code here
initPins();
while(1){
//the code to loop continuously goes here
Exercise 2
Switch on the LED when the user button is pushed. To do this follow the
following steps:
1. Find out to which microcontroller pin the user button is connected (refer
to chapter 5.5 of the Nucleo user manual)
2. Enable the clock to this pin and the LED pin.
3. Initialize these pins
4. Read the button input (the electrical connection of the button to the
microcontroller can be found in figure 25 of the Nucleo user manual).
5. Switch on the LED when the button is pushed using polling.
Exercise 3
A problem occurring often is that buttons physically bounce when pushed. The
effect of this is that instead of switching on neatly, the button input might flicker
a few times before staying on. You can compensate for this by letting your code
check if the button input is stable over a longer period. Toggle the LED state
when you press the user button: switch the LED on when the user button is
pushed and off when it is pushed again. If the button seems to “fail” sometimes
when you press it, you are experiencing bouncing.
8.2 Interrupts
Alternative to polling, event based interrupts can be used. In this way of design-
ing a process, the processor does not check for input, but a set event will trigger
the processor to jump to a certain part of your code. In the case of the switching
24
of the LED it would be more convenient if we could write a program which exe-
cutes the function setLED() when the button input becomes high, and performs
the function resetLED() when the button input becomes low. This means we
only have to execute code when the button input changes. In your code you can
program at which events you want the microcontroller to generate an interrupt
and how to handle this when this happens. Some examples of things which can
generate interrupts are changing levels on input pins (pin change interrupts),
periodic interrupts (timer interrupts) or input on communication busses (e.g.
SPI interrupts).
To enable an interrupt for a specific function, you first have to enable the Nested
Vector Interrupt Controller (NVIC), for the specific interrupt vector. After an
event occurs for which you enabled the interrupt, the program pointer automat-
ically switches to a callback function, called the interrupt service routine (ISR)
or interrupt handler. In this function you must clear the interrupt flag. An
example for enabling an interrupt and an interrupt handler is given in snippet
14. All interrupt registers can be found in chapter 10 of the reference manual.
// the ISR:
void EXTI0_IRQHandler(void)
{
if(EXTI->PR & 1) {
// do some fancy stuff
}
EXTI->PR |= 1; //clear interrupt flag of EXTI0 by writing a 1.
}
Exercise 4
In exercise 3 polling was used to read out the button. A good exercise before
going on to timers would be to try it with an interrupt. Enable the interrupt
for the user button, then write an interrupt service routine in which you toggle
the LED.
25
Table 10 Comparison of polling and interrupts
Polling Interrupts
Principle Let the processor check if inputs have Execute code immediately at
changed an event
Implementation A while(1){} loop (very easy) Event triggers and event
handlers (less simple)
Robustness Code is always executed in the same Interrupts can cause delays
order without interruption at unwanted moments,
causing errors.
Reaction time Every time the loop is executed Immediately
Processor time costs The processor wastes clock ticks on The processor only executes
checking variables which are the same code when an event takes
most of the time. place.
Power consumption Processor always runs at 100% : energy Processor can run slower
consumption is always maximum. when there is no event,
saving power.
26
9 Timers
A peripheral found in all microcontrollers is the timer. Timers is a counter fed
by a clock. It can be considered to be a register which increments or decrements
(depending on the timer settings) by one on every tick of a clock connected to
it.
The microcontroller on the Nucleo has seven general purpose timers: TIM2
-TIM5 and TIM9 - TIM11 of which the latter only count upwards. The timers
can be fed with different clock sources, internally or externally. This clock
source is fed through a programmable 16-bit clock divider called "prescaler" to
generate a clock signal for the timer. If the counter TIMx_CNT reaches a so
called auto-reload value TIMx_ARR it resets the counter to zero and throws a
event.
The counter is connected to four input capture/ output compare channels
TIMx_OC. These channels can be connected to a output pin and can work in
different modes ranging from measuring the pulse length on a input to toggle a
output. In figure 1 a simplified sketch is made to give insight in the purpose of
the auto-reload and the output compare registers. Of course is this only one of
the possible modes of operation. Look in the reference manual in chapter 13 or
14 for more in depth information about which registers to use.
There are also timers with more specific task: The main purpose of a watch-
dog is to check whether or not the code not hangs, it does this by being set
periodically to an initial value, if for some reason this does not happen, then
the device gets reset or an event is thrown.
Another timer is the Systick timer. This timer runs on the background and is
used to generate so called ticks which are used by a realtime operating system
to schedule slots for the different task.
Exercise 5
Use a Timer 2 to make an LED blink. To do this follow the following steps
1. Set up the the LED as output.
27
Table 11 List of possible GPIO settings in ARM microcontrollers
TIMx_CR1 13.4.1 Control register one Main control register, used for enabling the
counter and setting the counter mode
TIMx_CR2 13.4.2 Control register two Second control register, used for setting DMA
and other triggering
TIMx_SMCR 13.4.3 Slave mode control Settings used for using the timer in slave mode
register
TIMx_DIER 13.4.4 DMA / interupt Used for enabling the different interupt/ dma
enable register events
TIMx_CCER 13.4.9 Capture/ Compare Setting for the polarity of the channels and
enable register enabling them
TIMx_DMAR 13.4.18DMA adress register The register containing the adress for burst
for full transfer DMA
28
Figure 1: Simplified timing diagram
29
10 Analog Peripherals
Like most microcontrollers, the used STM32F411 microcontroller has an inter-
nal analog to digital converter (ADC). There are 19 input channels to select:
16 GPIO channels, an internal reference voltage, an internal temperature sen-
sor and a battery voltage monitoring feature, connected via an internal voltage
divider. To function properly, the ADC requires a proper ADCCLK clock,
from the ADC prescaler. An overview of this can be seen in figure 2, from the
STM32F411 reference manual.
The ADC can be started from various triggers, both internal and external,
and can generate interrupts when done. It also supports several modes: single
conversion mode, free running mode (convert a single channel continuously),
and group conversion (convert a group of channels in sequence, in arbitrary
order). When reading the reference manual, the difference between injected and
regular channels can be a bit unclear, so for clarity: the injected channels can
have a higher priority than the regular ones, making it possible to interrupt a
regular conversion group for an injected conversion.
Exercise 6
Use the ADC to read the output voltage of the potentiometer on the custom
shield and use it to alter the LED blinking frequency. To do this, follow the
following steps:
1. Find the right ADCCLK frequency from the datasheet, and set (and en-
able it).
2. Find, from the reference manual, what has to be done to use the ADC.
3. Set the ADC to continuously running mode, on the channel for the right
IO pin.
4. Find out what bit is set when the ADC is done.
5. Implement polling for this bit in your main loop from the timer example.
Set the blinking frequency for the LED when required.
6. Replace the polling routine by an interrupt for faster code, by enabling
the ADC interrupt. (Or continue to the next exercise).
Exercise 7
Polling the ADC to check whether it has finished yet cost processor clock ticks,
and results in a false answer most of the time. It thus is a waste of processor
resources to do this using polling. A more elegant and processor efficient ap-
proach to execute a routine when the ADC has finished would be by having the
ADC generate an interrupt when it has finished. To do this, replace the polling
routine by an interrupt by enabling the ADC interrupt.
30
Figure 2: ADC block diagram
31
11 SPI
For communicating with other chips several standards have been devised. The
simplest to implement is the Serial Peripheral Interface (SPI). SPI is a 4-wire
master-slave serial interface with signals for clock (SCK), master out slave in
(MOSI), master in slave out (MISO) and chip select (CS, sometimes slave select
called). The master device controls sets the clock and the chip select. Because
SPI is a loose standard the polarity of the clock (rising or falling edge) and chip
select are not set in stone. Below in figure 3 is a timing diagram of the interface.
Exercise 8
1. Look in the datasheet of the AD5611 to see how many bits need to be
transmitted, and on which bits the data needs to be present.
2. Find the needed clock polarity (CPOL) and clock edge (CKE).
3. Calculate the maximum SPI speed for the DAC and the used system clock.
4. Set up SPI1 for the correct SPI Mode, framesize and frequency.4
5. Optional Try to send the value of the potentiometer to the DAC, to make
sure the settings are correct.
32
12 Project: build a Function Generator
13 Energy Consumption
33
A Nucleo Board Hints
This appendix will contain some hints we’ve collected for the Nucleo F411RE
board.
34
B Function Generator Shield
In table 13 the connections of the Shield components to the Arduino header
and STM32F411RE microcontroller can be found. LEDx are the LEDs, BUTx
the three buttons, POT is the analog input of the potentiometer and CS, MOSI
and SCK are connected to the DAC. Although you can use the capacitive touch
buttons, P1 to P4, on the shield, it requires some additional programming.
Table 13 Pin connections of the shield to the Arduino header and STM32F411RE microcontroller.
35
List of Tables
1 Integer data types in C . . . . . . . . . . . . . . . . . . . . . . . 13
2 Floating point data types in C . . . . . . . . . . . . . . . . . . . 13
3 List of logical operators on words . . . . . . . . . . . . . . . . . . 16
4 Processing of a logical operation on a word . . . . . . . . . . . . 16
5 List of bitwise operators . . . . . . . . . . . . . . . . . . . . . . . 17
6 Processing of a bitwise operator . . . . . . . . . . . . . . . . . . . 17
7 Example of clearing of a single bit . . . . . . . . . . . . . . . . . 17
8 Step by step explanation of the code in snippet 7 . . . . . . . . . 17
9 List of possible GPIO settings in ARM microcontrollers . . . . . 23
10 Comparison of polling and interrupts . . . . . . . . . . . . . . . . 26
11 List of possible GPIO settings in ARM microcontrollers . . . . . 28
12 STLink connections for a cut Nucleo board. . . . . . . . . . . . . 34
13 Pin connections of the shield to the Arduino header and STM32F411RE
microcontroller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Code Snippets
1 84MHz system clock configuration for Nucleo-F411RE . . . . . . 10
2 Example of an integer as a Boolean . . . . . . . . . . . . . . . . . 13
3 Example code for reading and writing of an array . . . . . . . . . 14
4 Example of defining and working with a struct . . . . . . . . . . 14
5 Example of a state machine using enumerated type . . . . . . . . 15
6 Example of compound statements . . . . . . . . . . . . . . . . . . 16
7 Example of the clearing of a single bit in a register . . . . . . . . 17
8 Example of an if statement with and without an else clause . . . 18
9 Example of a switch statement . . . . . . . . . . . . . . . . . . . 18
10 Example of a for loop . . . . . . . . . . . . . . . . . . . . . . . . 19
11 Example of a while loop . . . . . . . . . . . . . . . . . . . . . . . 19
12 Example of a function . . . . . . . . . . . . . . . . . . . . . . . . 20
13 Example of using a while(1) loop and polling . . . . . . . . . . . 24
14 Example of enabling an interrupt and ISR . . . . . . . . . . . . . 25
36