Programming with STM32 Nucleo Boards

Page 1

STM32 NUCLEO BOARDS Dogan Ibrahim

Prof Dr Dogan Ibrahim has a BSc degree in electronic engineering, an MSc degree in automatic control engineering, and a PhD degree in digital signal processing. He has worked in many industrial organizations before he returned to academic life. Prof Ibrahim is the author of over 60 technical books and over 200 technical articles on microcontrollers, microprocessors, and related fields. He is a Chartered electrical engineer and a Fellow of the Institution of Engineering Technology.

ISBN 978-1-907920-68-4

STM32 Nucleo family of processors are manufactured by STMicroelectronics. These are low-cost ARM microcontroller development boards. This book is about developing projects using the popular Nucleo-L476RG development board. In the early Chapters of the book the architecture of the Nucleo family is briefly described. Software development tools that can be used with the Nucleo boards such as the Mbed, Keil MDK, TrueSTUDIO, and the System Workbench are described briefly in later Chapters. The book covers many projects using most features of the NucleoL476RG development boards where the full software listings for Mbed and System Workbench are given for every project. The projects range from simple flashing LEDs to more complex projects using modules and devices such as GPIO, ADC, DAC, I2C, LCD, analog inputs and others. In addition, several projects are given using the Nucleo Expansion Boards, including popular expansion boards such as: solid-state relay, MEMS and environmental sensors, DC motor driver, Wi-Fi, and stepper motor driver. These Expansion Boards plug on top of the Nucleo development boards and simplify the task of project development considerably. Features of this book • Learn the architecture of the STM32 microcontrollers • Learn how to use the Nucleo-L476RG development board in projects using Mbed and System Workbench Toolchains

Elektor International Media BV

www.elektor.com

LEARN DESIGN

• Learn how to use the Nucleo Expansion Boards with the Nucleo development boards

PROGRAMMING WITH STM32 NUCLEO BOARDS ● DOGAN IBRAHIM

PROGRAMMING WITH

PROGRAMMING WITH

STM32 NUCLEO BOARDS

Dogan Ibrahim LEARN DESIGN SHARE

SHARE

LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHAR GN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHAR


Contents

Table of Contents About the Author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 PREFACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Chapter 1 ● STM32 NUCLEO DEVELOPMENT BOARDS . . . . . . . . . . . . . . . . . . . . . . . . 12 1.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.2 ● STM32 Nucleo Development Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.2.1 ● Nucleo-32 Development Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.2.2 ● Nucleo-64 Development Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.2.3 ● Nucleo-144 Development Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.3● The Nucleo-L476RG Development Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.3.1 ● Two Part Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.3.2 ● The Power Supply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.3.3 ● The LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.3.4 ● Push-button Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.3.5 ● Jumper JP6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.3.6 ● The ST-LINK/V2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.3.7 ● Input-Output Connectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.3.8 ● The Demo Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.4 ● Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Chapter 2 ● STM32 NUCLEO EXPANSION BOARDS . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.2 ● STM32 Nucleo Expansion Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.2.1 ● Bluetooth Low Energy Expansion Board (X-NUCLEO-IDB04A1) . . . . . . . . . . 26 2.2.2 ● Wi-Fi Expansion Board (X-NUCLEO-IDW01M1) . . . . . . . . . . . . . . . . . . . . 27 2.2.3 ● Stepper Motor Expansion Board (X-NUCLEO-IHM01A1) . . . . . . . . . . . . . . . 28 2.2.4 ● Two Axis Stepper Motor Board (X-NUCLEO-IHM02A1) . . . . . . . . . . . . . . . . 29 2.2.5 ● High Power Stepper Motor Board (X-NUCLEO-IHM03A1) . . . . . . . . . . . . . . 30 2.2.6 ● Low Voltage Stepper Motor Board (X-NUCLEO-IHM06A1) . . . . . . . . . . . . . 31 2.2.7 ● Three-Phase Brushless DC Motor Board (X-NUCLEO-IHM07M1) . . . . . . . . . 32 2.2.8 ● Low Voltage Three-Phase Brushless DC Motor Board (X-NUCLEO-IHM11M1) . . 33 2.2.9 ● Multifunctional Expansion Board (X-NUCLEO-IKA01A1) . . . . . . . . . . . . . . . 34 2.2.10 ● Motion MEMS and Environmental Sensor Board (X-NUCLEO-IKS01A1) . . . . 35 2.2.11 ● 16 Channel LED Driver Board (X-NUCLEO-LED16A1) . . . . . . . . . . . . . . . 36 2.2.12 ● Dynamic NFC Tag Board (X-NUCLEO-NFC01A1) . . . . . . . . . . . . . . . . . . . 37 2.2.13 ● NFC Card Reader Board (X-NUCLEO-NFC03A1) . . . . . . . . . . . . . . . . . . . 38

●7


Programming with STM32 Nucleo Boards 2.2.14 ● Industrial Digital Output Board (X-NUCLEO-OUT01A1) . . . . . . . . . . . . . . 39 2.2.15 ● Industrial Input/Output Board (X-NUCLEO-PLC01A1) . . . . . . . . . . . . . . . 40 2.2.16 ● Ranging and Gesture Detection Board (X-NUCLEO-53L01A1) . . . . . . . . . . 41 2.3 ● Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Chapter 3 ● STM32 NUCLEO SOFTWARE DEVELOPMENT TOOLS (TOOLCHAINS) . . . . . 43 3.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.2 ● Integrated Development Environment Supporting the Nucleo Boards . . . . . . . . . 43 3.3 ● Embedded Workbench for ARM (EWARM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.3.1 ● Installing the EWARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.4 ● ARM Mbed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.5 ● MDK-ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.6 ● TrueSTUDIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 3.7 ● System Workbench for STM32 (SW4STM32) . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.8 ● Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Chapter 4 ● STM32 NUCLEO PROCESSOR ARCHITECTURE . . . . . . . . . . . . . . . . . . . . . 56 4.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.2 ● ARM Processors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.2.1 ● Cortex-M . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.2.2 ● Cortex-R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.2.3 ● Cortex-A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.2.4 ● Cortex-M Processor Comparison . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.2.5 ● Processor Performance Measurement . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.2.6 ● Cortex-M Compatibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.3● The STM32L476RGT6 Microcontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.3.1 ● Basic Features of the STM32L476RGT6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.3.2 ● Internal Block Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.3.3 ● General Purpose Inputs and Outputs (GPIOs) . . . . . . . . . . . . . . . . . . . . . 64 4.3.4 ● Electrical Characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.3.5 ● The Power Supply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.3.6 ● Low Power Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 4.3.7 ● The Clock Circuit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 4.3.8 ● Analog to Digital Converter (ADC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.3.9 ● Digital to Analog Converter (DAC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.3.10 ● Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.3.11 ● Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 4.4 ● Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

●8


Contents Chapter 5 ● EXAMPLE PROGRAMS USING THE IDEs (TOOLCHAINS) . . . . . . . . . . . . . . 76 5.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.2 ● Using the ARM Mbed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 5.3 ● The STM32CubeMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 5.3.1 ● Downlading the STM32CubeMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 5.3.2 ● Using the STM32CubeMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 5.4 ● Using the Keil MDK-ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 5.5 ● Using the TrueSTUDIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 5.6 ● Using the System Workbench for STM32 (SW4STM32) . . . . . . . . . . . . . . . . . . . 98 5.7 ● Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Chapter 6 ● STM32 NUCLEO-L476RG PROJECTS . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.1.1 ● System Workbench GPIO Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 6.2 ● PROJECT 1 – Lighthouse Flashing LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.3 ● PROJECT 2 – Alternately Flashing LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 6.4 ● PROJECT 3 – Rotating LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 6.5 ● PROJECT 4 – Binary Up Counter With LEDs . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.6 ● PROJECT 5 – Random Flashing LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 6.7 ● PROJECT 6 – Push-Button and LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 6.8 ● PROJECT 7 – LED Dice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 6.9 ● PROJECT 8 – 7-Segment LED Counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 6.10 ● PROJECT 9 – Two-Digit Multiplexed 7-Segment LED . . . . . . . . . . . . . . . . . . . 143 6.11 ● PROJECT 10 – Two-Digit 7-Segment Event Counter . . . . . . . . . . . . . . . . . . . 150 6.12 ● PROJECT 11 – Two-Digit 7-Segment LED With Timer Interrupts . . . . . . . . . . . 156 6.13 ● PROJECT 12 – Using LCDs – Displaying Text . . . . . . . . . . . . . . . . . . . . . . . . 168 6.14 ● PROJECT 13 – Using LCDs – Simple Counter . . . . . . . . . . . . . . . . . . . . . . . . 178 6.15 ● PROJECT 14 – Analog Temperature Sensor . . . . . . . . . . . . . . . . . . . . . . . . . 180 6.16 ● PROJECT 15 – LED With Variable Flashing Rate . . . . . . . . . . . . . . . . . . . . . . 188 Chapter 7 ● SERIAL COMMUNICATION WITH a PC . . . . . . . . . . . . . . . . . . . . . . . . . 192 7.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 7.2 ● Serial Communication Program on a PC . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 7.3 ● Mbed Serial Communication Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 7.3.1 ● Using the scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 7.4 ● PROJECT 16 – Event Counter With PC Monitor . . . . . . . . . . . . . . . . . . . . . . . 197 7.5 ● PROJECT 17 – Analog Temperature Sensor With PC Monitor . . . . . . . . . . . . . . 198 7.6 ● Debugging With the Help of the Serial Link . . . . . . . . . . . . . . . . . . . . . . . . . 199 7.7 ● Using the Serial Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

●9


Programming with STM32 Nucleo Boards 7.8 ● Using the System Workbench in Serial Communication . . . . . . . . . . . . . . . . . 201 7.9 ● PROJECT 18 – Parking Sensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Chapter 8 ● DIGITAL to ANALOG CONVERTER (DAC) . . . . . . . . . . . . . . . . . . . . . . . 216 8.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 8.2 ● PROJECT 19 – Sawtooth Waveform Generator . . . . . . . . . . . . . . . . . . . . . . . 216 8.3 ● PROJECT 20 – Sine Waveform Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Chapter 9 ● PULSE WIDTH MODULATION (PWM) . . . . . . . . . . . . . . . . . . . . . . . . . . 223 9.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 9.2 ● Basic Theory of the Pulse Width modulation . . . . . . . . . . . . . . . . . . . . . . . . . 223 9.3 ● Mbed PWM Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 9.4 ● PROJECT 21 – Mosquito Repeller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Chapter 10 ● I2C BUS INTERFACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 10.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 10.2 ● The I2C Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 10.3 ● Mbed I2C Bus Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 10.4 ● PROJECT 22 – Port Expander . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Chapter 11 ● USING THE EXPANSION BOARDS . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 11.1 ● Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 11.2 ● Using Digital Output Expansion Board (X-NUCLEO-OUT01A1) . . . . . . . . . . . . 243 11.3 ● PROJECT 23 – Flashing LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 11.4 ● Brushed DC Motor Driver Expansion Board (X-NUCLEO-IHM13A1) . . . . . . . . . 253 11.5 ● PROJECT 24 – Controlling a Small Brushed DC Motor . . . . . . . . . . . . . . . . . . 256 11.6 ● Motion MEMS and Environmental Sensor Board (X-NUCLEO-IKS01A2) . . . . . . 260 11.7 ● PROJECT 25 – Reading Humidity, Temperature, and Atmospheric Pressure . . . 262 11.8 ● Wi-Fi Expansion Board (X-NUCLEO-IDW01M1) . . . . . . . . . . . . . . . . . . . . . . 265 11.9 ● PROJECT 26 – Get and Display IP Address and MAC Address . . . . . . . . . . . . . 267 11.10 ● PROJECT 27 – TCP/IP Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 11.11 ● Low Voltage Stepper Motor Driver Expansion Board (X-NUCLEO-IHM06A1) . . 274 11.12 ● PROJECT 28 – Stepper Motor Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 APPENDIX – USING THE SYSTEM WORKBENCH PROJECT FOLDERS . . . . . . . . . . . . . 283 INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286

● 10


Programming with STM32 Nucleo Boards

Chapter 1 ● STM32 NUCLEO DEVELOPMENT BOARDS 1.1 ● Overview

This Chapter is about the STM32 Nucleo development boards. Brief specifications of the various Nucleo development boards are described in the Chapter. In addition, the details of the popular Nucleo-L476RG board is described in greater detail. 1.2 ● STM32 Nucleo Development Boards

STMicroelectronics is a company with a reputation of supplying quality microcontroller development boards and various hardware and software development tools. The Nucleo family of low-cost development boards are small but powerful boards based on the 32-bit ARM Cortex architecture. These development boards are targeted for a large audience, including students, professional engineers, and hobbyists at all levels. The boards are compatible with the popular Arduino, mbed, ST-LINK, and ST Morpho, making it accessible to users with different backgrounds. There are over 30 different boards in the Nucleo family, aimed to satisfy the needs of almost all users. The Nucleo boards come in three different sizes: small (Nucleo-32), short (Nucleo-64), and long (Nucleo-144) where the numbers refer to the pin counts of the MCUs. These three groups are further divided into three sub-groups: ultra-low power (green), mainstream (blue), and high performance (magenta). The ultra-low power boards are based on the STM32 L family and these boards are targeted for low-power applications, such as watches, smart meters etc. Examples of the ultra-low power boards are: Nucleo-L011K4, Nucleo-L031K6 and Nucleo-L432KC. There are three sub-categories in the STM32 L family: • L0, ARM Cortex-M0+ • L1, ARM Cortex-M3 • L4, ARM Cortex-M4 About half of the STM32 Nucleo boards are in the mainstream category. Examples of the mainstream boards are: Nucleo-F303K8, Nucleo-F042K6, Nucleo-F303RE etc. There are three sub-categories in the mainstream category: • F0, ARM Cortex-M0+ • F1, ARM Cortex-M3 • F3, ARM Cortex-M4 The high-performance boards have large memories and faster MCUs. Examples of high-performance boards are: Nucleo-F410RB, Nucleo-F401RE, Nucleo-F722ZE etc. There are three sub-categories in the high-performance category: • F2, ARM Cortex-M3 • F4, ARM Cortex-M4 • F7, ARM Cortex-M7 The Nucleo-32 boards are small (50mm x 19mm) and are Arduino Nano compatible. Nucleo-64 and nucleo-144 are Arduino Uno compatible and they also have ST Morpho exten-

● 12


Chapter 1 ● STM32 NUCLEO DEVELOPMENT BOARDS

sion connectors which carry the MCU pins. There are large number of Arduino Nano/Uno compatible shields available in the market and these shields can easily be used with the Nucleo boards, making it easy to quickly develop projects using the Nucleo boards Depending upon the model the Nucleo boards have flash program memory sizes from 16KB up to 2MB, and RAM memories from 4KB to 320KB. The clock frequency varies from 32MHZ to 216MHz. Figure 1.1 shows a comparison of the Nucleo boards.

[Figure 1.1 Nucleo boards. (©STMicroelecronics. Used with permission)] 1.2.1 ● Nucleo-32 Development Boards

Figure 1.2 shows an example Nucleo-32 board, the Nucleo-L031K6. This is an ultra-low power low-cost board incorporating the STM32L031K6T6 microcontroller. The board is Ar-

● 13


Chapter 2 ● STM32 NUCLEO EXPANSION BOARDS

Chapter 2 ● STM32 NUCLEO EXPANSION BOARDS 2.1 • Overview

This Chapter is about the STM32 Nucleo expansion boards. With the help of the expansion boards we can easily and quickly develop complex microcontroller based projects. Brief specifications of the various popular expansion boards are given in this Chapter. 2.2 • STM32 Nucleo Expansion Boards

The expansion boards are equipped with Arduino Uno or ST morpho compatible connectors. These boards are tested hardware and they are plugged on top of the Nucleo boards. Expansion boards help us to build projects quickly and with little effort since these boards are supported by the STM32 based software modules. The combination of STM32 Nucleo boards and expansion boards is a unified scalable approach with unlimited possibilities for application development, prototyping or product evaluation. Further information on the Nucleo expansion boards can be obtained from the following ST web site: http://www.st.com/en/evaluation-tools/stm32-nucleo-expansion-boards.html? querycriteria=productId=SC1971 All of the pictures of Expansion Boards in this Chapter are the copyright of STMicroelectronics and have been used here with their written permission: ©STMicroelectronics. Used with permission.

● 25


Programming with STM32 Nucleo Boards

2.2.1 • Bluetooth Low Energy Expansion Board (X-NUCLEO-IDB04A1)

The X-NUCLEO-IDB04A1 is a Bluetooth low energy board (Figure 2.1) that gives the Bluetooth communications capability to the Nucleo boards. This board is compatible with the Arduino Uno connectors. The X-NUCLEO-IDB04A1 is interfaced with the STM32 MCU via the SPI bus. The basic specifications of the Bluetooth board are: • BlueNRG low power and low energy • Bluetooth low energy 4.0 master and slave compliant • Low current consumption (7.3mA RX and 8.2mA TX) • 8dBm maximum transmission power • -88 dBm receiver sensitivity

[Figure 2.1 Bluetooth low energy expansion board]

● 26


Chapter 3 ● STM32 NUCLEO SOFTWARE DEVELOPMENT TOOLS (TOOLCHAINS)

CHAPTER 3 • S TM32 NUCLEO SOFTWARE DEVELOPMENT TOOLS (TOOLCHAINS) 3.1 • Overview

This Chapter is about the software development tools (Integrated Development Environments, IDEs, or Toolchains) that can be used to develop software for the Nucleo boards. Brief specifications of the popular Nucleo development tools are given in the Chapter. 3.2 • Integrated Development Environments Supporting the Nucleo Boards

The Nucleo boards are supported by several software development tools in the form of Integrated Development Environments (IDEs). In general, most IDEs provide a built-in text editor, compiler, debugger, simulator, and a program upload tool so that the developed program code can be uploaded to the program memory of the target microcontroller. The compiler is usually a version of C/C++. Some of the popular IDEs supporting the Nucleo boards are: • Embedded Workbench for ARM (EWARM) by IAR Systems • ARM Mbed • MDK-ARM by Keil • TrueSTUDIO for STM32 • System Workbench for STM32 (SW4STM32) by AC6 Brief details of these IDEs are given in the following sections. Examples of using these IDEs with the Nucleo-L476RG board will be given in Chapter 5. 3.3 • Embedded Workbench for ARM (EWARM)

This is a professional compiler developed by the IAR Systems. The compiler is based on a highly optimizing C/C++ and it supports devices based on ARM Cortex-M0, Cortex-M0+, Cortex-M3, Cortex-M4, and Cortex-M7. A debugger with simulator is supported by the EWARM. Two free evaluation versions of the software are available: time limited version, and code size limited version. The differences between the two versions are: 30 day time limited version

• License will expire after 30 days • Source code for runtime libraries is not included • No support for MISRA C • C-RUN is size limited to 12 KB of code, excluding constant data • Limited technical support • Must not be used for commercial product development Size limited version

• Code size limited to 32KB • Source code for runtime libraries is not included • No support for MISRA C

● 43


Programming with STM32 Nucleo Boards

• C-RUN is not available • Limited technical support When you start the product the first time you will be asked to register to get the evaluation license. The choice between the time limited version and the code size limited versions is made after the product is installed. 3.3.1 • Installing the EWARM

• The steps to install the EWARM are as follows: • Download the IDE from the following link. At the time of writing this book the latest version was 8.20. The IDE occupied about 1.3GB and had the name EWARM-CD-8202-14838.exe: https://www.iar.com/iar-embedded-workbench/tools-for-arm/arm-cortex-medition/ • Copy the downloaded file to a folder and then double click on it to start the installation process. You should see the screen as in Figure 3.1 at the beginning of the installation. Click on the first option to start downloading. The installation process may take several minutes and you should wait until it is finished.

[Figure 3.1 Beginning of the installation]

• Register with the IAR Systems to get an evaluation license. You will have to confirm your registration by clicking at the link sent to your registration address. Enter the license number into the given form and you should then be able to use the product. Figure 3.2 shows the license details (click Help and then License Manager).

● 44


Programming with STM32 Nucleo Boards

CHAPTER 4 • STM32 NUCLEO PROCESSOR ARCHITECTURE 4.1 • Overview

In this Chapter we shall be looking at the internal architecture of the STM32 Nucleo processors. This is important for developing efficient programs and projects. The popular STM32L476RGT6 microcontroller will be considered as an example ARM processor. 4.2 • ARM Processors

The choice of a microcontroller for a particular application depends on many factors such as the following: • Cost • Speed • Power consumption • Size • Number of digital and analog input-output ports • Digital input-output port current capacity • Analog port resolution and accuracy • Program and data memory sizes • Interrupt support • Timer support • USART support • Special bus support (e.g. USB, CAN, SPI, I2C and so on) • Ease of system development (e.g. programming) • Working voltage For example, if you need to develop a battery powered device such as a mobile phone or a games device then very high clock speed as well as long battery life are main requirements. But if you are developing a traffic light controller then very high performance is not a requirement. In general, as the clock speed goes up so does the power consumption and as a result a trade-off should be made in choosing a microcontroller for a specific application. ARM has been designing 32-bit processors for over 20 years and in the last few years they have also started to offer 64-bit designs. In actual fact ARM is a company specialized in designing the processor architecture and they do not manufacture or sell processor chips. ARM makes money by licensing their designs to chip manufacturers. The manufacturers use the core ARM processors (e.g. the core CPU) and integrate with their own peripherals to end up in a complete microcontroller chip. ARM is then given royalty fees for each chip manufactured by the third party companies. Companies that use ARM core processors include Apple, Atmel, Broadcom, Cypress Semiconductors, Freescale Semiconductors, Analog Devices, Nvidia, NXP, Samsung Electronics, Texas Instruments, Qualcomm, Renesas, and many others. ARM was originally known as the Acorn Computers and they have developed the first Acorn RISC Machine (ARM) architecture in the 1980s to use in their personal computers. First ARM processors were co-processor modules used in the BBC Micro series. After failing to find suitable high performance microprocessor chips in the market, Acorn decided to

● 56


Chapter 4 • STM32 NUCLEO PROCESSOR ARCHITECTURE

design their own processors. In 1990, the research section of Acorn formed the ARM Ltd. Currently ARM is the most widely used processor in terms of quantity manufactured. Over 50 billion ARM processors have been produced as of 2014, where 10 billion were produced only in 2013. The ARM 32-bit architecture is the most widely used in mobile devices where about 98% of all mobile phones sold in the year 2005 used at least one ARM processor. The ARM architecture is known to offer the best MIPS to Watts ratio as well as MIPS to $ ratio in the industry, and the smallest CPU size. The small size, low power consumption, and low cost make ARM an ideal processor in embedded applications. ARM processors are based on an instruction set called Thumb. With clever design this instruction set takes 32-bit instructions and compresses them down to 16-bits, thus reduces the hardware size, which also reduces the overall cost. The processor makes use of multi stage pipelined architecture that is easier to learn, build, and program. ARM processors are based on the RISC (Reduced instruction Set Computer) architecture and are available as 32-bit or 64-bit multi-core structures. RISC processors, as opposed to CISC (Complex Instruction Set Computer) processors have smaller number of instructions and fewer transistors (hence smaller die size), as a result they can operate at higher speeds. Unimportant or not frequently used instructions are removed and the pathways are optimized to result in superior performance. It is important to realize that ARM’s core architecture is only a processor and it does not include graphics, input-output ports, USB, serial communication, wireless connectivity, or any other form of peripheral modules. Chip manufacturers build their systems around the ARM core design and this is why different manufacturers offer different types of ARM based microcontrollers. Over the last 20 years or so ARM had developed many 32-bit processors. Figure 4.1 shows some of the popular members of the ARM processor family. The first successful member was the ARM7TDMI which had high code density and low power consumption. This processor, based on the Von Neumann architecture was operating at 80MHz and was used in early mobile phones. ARM9 was developed in 1997 with Harvard architecture and operated with 150MHz, thus offered higher performance. ARM10 and ARM11 were developed in the years 1999 and 2003 respectively. Both of these processors were based on the Harvard architecture. ARM10 operated at 260MHz and ARM11 operated at 335MHz. Around the year 2003 ARM decided to improve their market share by developing new series of high performance processors. As a result, the Cortex family or processors were created. The Cortex family consists of 3 processor families: Cortex-M, Cortex-R, and Cortex-A. We shall now briefly look at these families.

● 57


Programming with STM32 Nucleo Boards

[Figure 4.13 STM476xx clock circuit] External Clock Sources

High Speed External (HSE): This can be an external crystal or resonator device, or an external clock signal. The frequency range of the crystal or resonator should be 4-48MHz. Figure 4.14 shows a typical crystal connection. It is recommended to use two capacitors in the range of 4-25pF with the crystal circuit.

[Figure 4.14 Crystal oscillator connection]

When using a clock generator circuit, the waveform can be square, sine, or triangular, and the waveform must be symmetrical i.e. 50% ON and 50% OFF times. The clock signal must be fed to the OSC_IN pin of the microcontroller (Figure 4.15). If external clock circuitry is used then HSE oscillator should be bypassed to avoid any conflict.

â—? 72


Chapter 4 • STM32 NUCLEO PROCESSOR ARCHITECTURE

[Figure 4.15 Using clock generator circuit]

Low Speed External (LSE): This is a 32,768Hz clock driven from an external crystal and feeding the internal Real Time Clock (RTC) module. Internal Clock Sources

High Speed Internal (HSI): This is an accurate RC based 16MHz internal clock with a factory calibrated tolerance of 1%. Multispeed Internal (MSI RC): This is a multispeed RC based clock source providing clock in the range 100kHz to 48MHz. This clock can be trimmed by software and is able to generate 12 different clock frequencies. PLL: The PLL is fed by HSE, HIS or MSI clocks and it can generate system clocks up to 80MHz. Microcontroller Clock Output (MCO)

A clock output is possible from a special pin called Microcontroller Clock Output (MCO). This clock output can be used as a general purpose clock or as a clock for another microcontroller. Low Speed Clock Output (LSCO)

A low speed (32.768kHz) clock (LSCO) is available as a general purpose clock output. Several pre-scalers are available in the clock circuit to configure the AHB, APB1 and APB2 bus clock frequencies for the system and the peripheral devices. The maximum frequency of the AHB and APBx is 80MHz. Configuring the Clock

As shown in Figure 4.12 and Figure 4.13, the clock circuit consists of a number of multiplexers, pre-scalers, and a Phase Locked Loop (PLL). The multiplexers are used to select the required clock source. The pre-scalers are used to divide the clock frequency by a constant. Similarly, the PLL is used to multiply the clock frequency with a constant in order to operate the chip at higher frequencies. It is important to select the correct clock source for an application. Configuring the clock sources by programming the internal clock registers is a complex task and detailed knowledge of the clock circuitry is required. In reference to Figure 4.12 and Figure 4.13, we can identify the following pre-scalers:

â—? 73


Programming with STM32 Nucleo Boards

CHAPTER 5 • EXAMPLE PROGRAMS – USING THE IDEs (TOOLCHAINS) 5.1 • Overview

In this Chapter we will be developing a very simple application using the various IDEs (or toolchains) described in Chapter 3 so that the reader is familiar with using these tools. The application described here simply flashes the user LED on the Nucleo-L476RG development board every second. This LED is connected to port pin PA_5 (pin 5 of port A) or to Arduino connector pin D13 of the development board through a current limiting resistor. Thus, the LED is turned ON when logic 1 is sent to this port, and turned OFF when logic 0 is sent to the port. 5.2 • Using the ARM Mbed

ARM Mbed is an online tool where a program is written and compiled online through the Internet. Mbed site includes a large number of sample programs and tutorials that can be useful while learning how to program using the Mbed. Before programming using Mbed it is important to know the pin names of the connectors on the board that we will be using. Figure 5.1 and Figure 5.2 show the pin names of the two morpho connectors CN7 and CN10 on the Nucleo-L476RG board (see: https://os.mbed.com/platforms/ST-Nucleo-L476RG/). As it can be seen from Figure 5.2, the pin name of the user LED is LED1 (pin PA_5 at the left on connector CN5).

[Figure 5.1 CN7 connector pin names]

● 76


Chapter 5 • EXAMPLE PROGRAMS – USING THE IDEs (TOOLCHAINS)(TOLCHAINS)

[Figure 5.2 CN10 connector pin names]

The steps to write a program to flash the user LED on the Nucleo-L476RG board are given below: • Login to the Mbed site • Click Compile • Click New-> New Program. You will see a list of sample programs. Click on Blinky LED test for the ST Nucleo boards (see Figure 5.3). Click OK.

[Figure 5.3 Click on the Blinky LED test program]

• C lick on main.cpp at the working space (middle part) of the screen to open the program listing (see Figure 5.4)

● 77


Chapter 5 • EXAMPLE PROGRAMS – USING THE IDEs (TOOLCHAINS)(TOLCHAINS)

[Figure 5.30 Created main C file]

Double click on file main.c to display it in the middle of the screen. You should see the initialization code, system clock generation code, input/output initialization code and lots of other code. For example, the clock configuration code is as follows: void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; /**Initializes the CPU, AHB and APB busses clocks*/ 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 = 1; RCC_OscInitStruct.PLL.PLLN = 10; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Initializes the CPU, AHB and APB busses clocks*/

● 95


Programming with STM32 Nucleo Boards

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure the main internal regulator output voltage*/ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure the Systick interrupt time*/ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); /**Configure the Systick*/ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); }

The input/output initialization code is as follows. Notice here that LD2_Pin is pin PA5 where the user LED is connected to: static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : B1_Pin */

● 96


Programming with STM32 Nucleo Boards

CHAPTER 6 • STM32 NUCLEO-L476 PROJECTS 6.1 • Overview

In the last chapter we have seen how various toolchains can be downloaded, installed and used in a very simple project. In this chapter we will be developing basic projects using the Nucleo-L476RG development board. The projects will be based on the Mbed and the System Workbench toolchains. Notice that all the project given in this book have been tested and are working. The following will be specified and given for each project: • Project title • Project description • Aim of the project • Project block diagram • Project circuit diagram • Project construction • Project program listing • Description of the program • Additional work (optional) The operation of some of the more complex projects will be described using the Program Description Language (PDL). This is a free format English like description of the operation of the project using keywords such as BEGIN, END, IF, THEN, ELSE, WHILE, REPEAT, DO, DO FOREVER, and so on. 6.1.1 • System Workbench GPIO Library

The GPIO code generated by the STM32CubeMX software is in the HAL library. The HAL library contains a large number of functions that can be used to develop applications using the STM32 processors. The HAL library offers high level and feature oriented APIs that can be used in STM32CubeMX toolchain to develop STM32 based projects. In this section we shall be looking briefly at the HAL GPIO library functions. The HAL library is initialized with the statement: HAL_Init(). The following GPIO functions are offered: A GPIO port is configured using a structure in the following format. In this example, GPIOA pin 0 is configured as an output: GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); We can combine the pins as in the following example: GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2; or, GPIO_InitStruct.Pin = GPIO_PIN_All;

● 100


Chapter 6 • STM32 NUCLEO-L476 PROJECTS

The GPIO ports are configured in function called MX_GPIO_Init which is called automatically from the main program when the program is created. The mode can take the following values: GPIO_MODE_INPUT Input Floating Mode GPIO_MODE_OUTPUT_PP Output Push Pull Mode GPIO_MODE_OUTPUT_OD Output Open Drain Mode GPIO_MODE_AF_PP Alternate Function Push Pull Mode GPIO_MODE_AF_OD Alternate Function Open Drain Mode GPIO_MODE_ANALOG Analog Mode GPIO_MODE_IT_RISING Ext. Int. with Rising edge detection GPIO_MODE_IT_FALLING Ext. Int. with Falling edge detection GPIO_MODE_IT_RISING_FALLING Ext. Int. with Rising/Falling edge detection GPIO_MODE_EVT_RISING Ext. Event Mode with Rising edge detection GPIO_MODE_EVT_FALLING Ext. Event Mode with Falling edge detection GPIO_MODE_EVT_RISING_FALLING Ext. Event Mode with Rising/Falling detection The speed can take the following values (refer to the data sheet): GPIO_SPEED_FREQ_LOW IO works at 2 MHz GPIO_SPEED_FREQ_MEDIUM 12,5 MHz to 50 MHz GPIO_SPEED_FREQ_HIGH 25 MHz to 100 MHz GPIO_SPEED_FREQ_VERY_HIGH 50 MHz to 200 MHz The pullup/down can be: GPIO_NOPULL GPIO_PULLUP GPIO_PULLDOWN

No Pull-up or Pull-down activation Pull-up activation Pull-down activation

HAL_GPIO_WritePin: This function is used to set (logic 1) or reset (logic 0) a GPIO pin. In the following example, pin 1 of GPIOA is set to logic 1: HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); Similarly, the same pin is reset to logic 0 using the following statement: HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); HAL_GPIO_ReadPin: This function is used to read the state of a GPIO pin. In the following example, the state of pin 1 of GPIOA is read and stored in variable called data: data = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1); HAL_GPIO_TogglePin: This function is used to toggle the state of a pin. In the following example the state of pin 8 of GPIOA is toggled: HAL_TogglePin(GPIO_PIN_8); HAL_GPIO_LockPin: This function is used to lock a port pin. The configuration of the locked pin cannot be changed until the next reset.

● 101


Chapter 6 • STM32 NUCLEO-L476 PROJECTS

6.6.5 • The Construction

The project is built on a breadboard as shown in Figure 6.13. 6.6.6 • Mbed Program Listing

The Mbed program listing of the project is shown in Figure 6.19 (program: RANDOM). At the beginning of the program header file mbed.h is included in the program and as in the previous project, an array called LEDS is used to store the pin numbers of the four GPIO ports where the LEDs are connected to. A function called Display is created to group a number of GPIO pins together so that they can be accessed together. Inside the main program function rand() is called to generate random numbers. Variable r stores the generated random number between 0 and 15. Function Display is called with variable r and number 4 (number of GPIO pins used) as its parameters. 250ms delay is inserted between each output where the LEDs flash randomly.

#include “mbed.h” DigitalOut LEDS[] = {(PA_9), (PA_8), (PA_7), (PA_6)}; // // Group 4 port pins together // void Display(char No, char L) { int j, m, i; m = L - 1; for(i = 0; i < L; i++) { j = pow(2.0, m); LEDS[i] = No & j; m--; } } int main() { int Count, r; while(1) { r = rand() % 16; Display(r, 4); wait(0.25); } }

// Generate random no betwwen 0-15 // Display Count in 4 bits // Wait 250ms

[Figure 6.19 Mbed Program listing] 6.6.7 • System Workbench Program Listing

Figure 6.20 shows the System Workbench program (folder: RANDOM) listing (the clock configuration and error handler routines are the same as in the previous programs and they have been removed from Figure 6.20 for clarity). Here, the math.h library is included in the project since we will be using the pow() function. Also, the stdlib.h library is included since we will be using the random function generator rand(). As in the Mbed program, here also a function called Display is created to group the GPIO pins

● 121


Programming with STM32 Nucleo Boards

together so that they can be accessed easily. Random numbers are generated each time round the loop and stored in variable r. These numbers are then sent to function Display to turn the LEDs ON and OFF randomly. 250ms delay is inserted between each output.

/* Includes ------------------------------------------------------------------*/ #include “main.h” #include “stm32l4xx_hal.h” #include “math.h” #include “stdlib.h” #define led1 #define led2 #define led3 #define led4 int LEDS[] =

GPIO_PIN_9 GPIO_PIN_8 GPIO_PIN_7 GPIO_PIN_6 {led1, led2, led3, led4};

/* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); // // Group the GPIO pins together // void Display(int No, int L) { int j, m, i; m = L - 1; for(i = 0; i < L; i++) { j = pow(2.0, m); if((No & j) != 0) HAL_GPIO_WritePin(GPIOA,LEDS[i],GPIO_PIN_SET); else HAL_GPIO_WritePin(GPIOA,LEDS[i],GPIO_PIN_RESET); m--; } } /* START OF MAIN PROGRAM */ int main(void) { int r; /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init();

}

while (1) { r = rand() % 16; Display(r, 4); HAL_Delay(250); }

// Generate random number // Turn LEDs ON/OFF // 250ms delay

static void MX_GPIO_Init(void) { int k;

● 122


Programming with STM32 Nucleo Boards

CHAPTER 7 • SERIAL COMMUNICATION WITH A PC 7.1 • Overview

The Nucleo-L476RG board is connected to the PC using a USB cable where power to the board is supplied through this cable. In this Chapter we shall be developing programs so that the Nucleo-L476RG board communicates with a PC over the USB cable that is also used for programming the processor on the board. There are several reasons why we may want to communicate with a PC: • Display messages on the PC monitor, e.g. to display the output of programs or for debugging a program • Read input from the PC keyboard, e.g. in application programs • Communicate with programs running on the PC We shall first look at the techniques of how serial communication with a PC can be established through the USB cable. 7.2 • Serial Communication Program on a PC

In order to communicate with a PC over a serial line we need to install a terminal emulator program on our PC. There are several freely available terminal emulation programs available on the Internet, such as HyperTerm, Putty, Tera Term and so on. In this Chapter we shall be using the HyperTerm program. Before we use a terminal emulation program to communicate over a serial port we need to know the following information about the device that we wish to communicate with: • Assigned serial port number • Speed of communication (i.e. Baud rate) • Databits (7 or 8) • Parity (even, odd, or none) • Stop bits (1 or 2) • Handshaking By default, the Nucleo-L476RG board has the following settings: 9600 baud, 8 data bits, no parity, 1 stop bit, and no handshaking. The serial port number can be obtained as follows (for Windows 7 systems): • Plug-in your Nucleo-L476RG board to the PC using the USB cable • Click Start and then click on the Control Panel • Click on System and then click on Device Manager • Click on Ports (COM & LPT) and check the STLink Virtual COM Port number. As an example, in Figure 7.1 the port number was COM48

● 192


Chapter 7 ● SERIAL COMMUNICATION WITH A PC

[Figure 7.1 Assigned serial port number]

Now we can write a very simple Mbed program to display text on the PC monitor: #include “mbed.h” Serial pc(USBTX, USBRX); int main() { pc.printf(“Message from the Nucleo-L476 board”); }

The Serial pc(USBTX, USBRX) statement creates a virtual serial port with the name pc. USBTX and USBRX are the names of the port that communicates over the USB cable with the PC. Start the HyperTerm program, set the port name to COM48 (or your own port name) and set the configuration parameters as shown in Figure 7.2.

[Figure 7.2 Configuring the HyperTerm]

● 193


Chapter 7 ● SERIAL COMMUNICATION WITH A PC

7.7 • Using the Serial Interrupt

We can attach the serial link to an interrupt service routine in our program so that for example every time a character is typed on the keyboard the interrupt service routine becomes activated. We can read the typed character and this way we can perform different operations inside the interrupt service routine depending upon the character typed. Figure 7.11 shows a program (program: SERINT) using a serial interrupt. In this program the user LED on the Nucleo-L476RG board is used (connected to port pin PA_5). In this program, every time character t is pressed on the keyboard the LED is toggled. The interrupt service routine is called ISR and it is attached to the serial link. Inside function ISR the typed character is checked and if it is t then the LED is toggled.

#include “mbed.h” Serial pc(USBTX, USBRX); DigitalOut myled(PA_5);

// LED port

// // Serial receive interrupt service routine // void ISR() { char c; c = pc.getc(); if(c == ‘t’)myled = !myled; } int main() { pc.attach(&ISR, Serial::RxIrq);

}

// Get the character // if “t” toggle LED

// Attach interrupt

while(1) { }

[Figure 7.11 Mbed program listing] 7.8 • Using the System Workbench in Serial Communication

Pins PA_2 and PA_3 on the Nucleo-L476RG board are the USART2 transmit (TX) and receive (RX) pins respectively. These pins are used to communicate with the PC during program loading and debugging. In this section we shall see how to use the USART2 to send a text message to the PC over the USB cable using the System Workbench. First of all, we shall start the STM32CubeMX program and configure it to use the USART2. The steps are as follows: • Start STM32CubeMX program • Start New Project and select the Nucleo-L476RG board as described in Chapter 6 • Select USART2 and set its mode to Asynchronous as shown in Figure 7.12. Notice that

● 201


Programming with STM32 Nucleo Boards

pins PA_2 and PA_3 are shown as USART_TX and USART_RX on the pin diagram in the middle of the screen.

[Figure 7.12 Select USART2 and set to Asynchronous]

• Click Clock Configuration tab and make sure the clock is enabled for the system and also for USART2 • Click Configuration tab and then click on USART2. Set the Baud Rate to 9600 and Word Length to 8 bits (including Parity), and set Parity to None as shown in Figure 7.13. Click Apply and then OK.

[Figure 7.13 Configure USART1]

• Select Project Settings and set the Toolchain to SW4STM32. Give a name to the project, click OK. • Click Project and then Generate Code.

● 202


Programming with STM32 Nucleo Boards

CHAPTER 8 • DIGITAL TO ANALOG CONVERTER (DAC) 8.1 • Overview

Digital to Analog converters (DACs) are used to provide analog outputs from digital processors. A DAC receives digital input, converts it into analog and outputs the analog data. There are 2 12-bit DACs on the Nucleo-L476RG, available at pins PA_4 and PA_5. In this Chapter we shall develop projects to output analog data through one of these DACs. ord AnalogOut. The variable name can then be used to send out analog data at the analog pin. The following functions are available with the AnalogOut: write: This function sends out analog data to the specified analog pin. Valid values are 0.0 to 1.0 where 0.0 corresponds to 0V and 1.0 corresponds to +3.3V. write_u16: This function sends out analog data to the specified analog pin. Valid values are 0 to 65535, where 0 corresponds to 0V and 65535 corresponds to +3.3V. read: This function returns the analog voltage sent to the specified analog pin. Returned values are 0.0 to 1.0. As an example, output of 0.25 corresponds to 0.25x3.3V = 0.825V. Similarly, output of 0.5 corresponds to 1.65V. 8.2 • PROJECT 19 – Sawtooth Waveform Generator 8.2.1 • Description

In this project we will write a program to create a sawtooth waveform. 8.2.2 • The Aim

The aim of this project is to show how the DAC of the Nucleo-L476RG can be used in a project. 8.2.3 • Circuit Diagram

Pin PA_4 (pin 32 on connector CN7) of the Nucleo-L476RG is connected to a digital oscilloscope to record the waveform. In this project the PCSGU250 Velleman oscilloscope/ transient analyser is used. 8.2.4 • Mbed Program Listing

The program listing of the project is shown in Figure 8.1 (program: SAWTOOTH). At the beginning of the program mbed.h and AnalogOut are included in the program where pin PA_4 is used as the analog output with variable name aout. A for loop is created where variable j is incremented in steps of 0.1 from 0 to 1. i.e. the generated sawtooth waveform has 10 steps. 1ms delay is inserted between each output so that each step has the duration of 1ms.

● 216


Chapter 8 ● DIGITAL TO ANALOG CONVERTER (DAC)

#include “mbed.h” AnalogOut aout(PA_4);

// Analog output

int main() { float j;

}

while(1) { for(j = 0.0f; j < 1.0f; j = j + 0.1f) { aout = j; wait(0.001); } }

// Analog output j // 1 ms delay

[Figure 8.1 Mbed program listing]

Figure 8.2 shows the generated waveform on the oscilloscope. Here, the horizontal axis is 5 ms and the vertical axis is 1 V. Notice that the period of the waveform is 10 ms.

[Figure 8.2 Display of the generated waveform] 8.2.5 • System Workbench Program

There are two 12-bit DAC that can be used independently or simultaneously (dual mode): • DAC channel1 with DAC_OUT1 (PA_4) as output • DAC channel2 with DAC_OUT2 (PA_5) as output We shall be using DAC_OUT1. The STM32CubeMX tool will be used to create a template for our DAC program. The steps are given below:

● 217


Chapter 9 ● PULSE WIDTH MODULATION (PWM)

CHAPTER 9 • PULSE WIDTH MODULATION (PWM) 9.1 • Overview

Pulse Width Modulation Digital (PWM) is commonly used to drive heavy loads such as motors, actuators and so on. As we shall see in this Chapter, PWM is basically a positive square waveform whose pulse width can be changed. By changing the pulse width we can effectively change the average voltage supplied to the load. In this Chapter we shall be developing a project for the Nucleo-L476RG board to generate a PWM waveform with a given frequency and pulse width. 9.2 • Basic Theory of the Pulse Width Modulation

Pulse Width Modulation (PWM) is a commonly used technique for controlling the power delivered to analog loads using digital waveforms. Although analog voltages (and currents) can be used to control the delivered power, they have several drawbacks. Controlling large analog loads require large voltages and currents that cannot easily be obtained using standard analog circuits and DACs. Precision analog circuits can be heavy, large, and expensive and they are also sensitive to noise. By using the PWM technique the average value of voltage (and current) fed to a load is controlled by switching the supply voltage ON and OFF at a fast rate. The longer the power on time, the higher is the voltage supplied to the load. Figure 9.1 shows a typical PWM waveform where the signal is basically a repetitive positive pulse, having the period T, ON time TON and OFF time of T – TON seconds. The minimum and maximum values of the voltage supplied to the load are 0 and VP respectively. The PWM switching frequency is usually set to be very high (usually in the order of several kHz) so that it does not affect the load that uses the power. The main advantage of PWM is that the load is operated efficiently since the power loss in the switching device is very low. When the switch is ON there is practically no voltage drop across the switch, and when the switch is OFF there is no current supplied to the load.

[Figure 9.1 PWM waveform]

The duty cycle (or D) of a PWM waveform is defined as the ratio of the ON time to its period. Expressed mathematically, Duty Cycle (D) = TON / T

● 223


Programming with STM32 Nucleo Boards

The duty cycle is usually expressed as a percentage and therefore, D = (TON / TOFF) x 100 % By varying the duty cycle between 0% and 100% we can effectively control the average voltage supplied to the load between 0 and Vp. The average value of the voltage applied to the load can be calculated by considering a general PWM waveform shown in Figure 1. The average value A of waveform f(t) with period T and peak value ymax and minimum value ymin is calculated as:

or, In a PWM waveform ymin = 0 and the above equation becomes

or,

A = D y max

As it can be seen from the above equation, the average value of the voltage supplied to the load is directly proportional to the duty cycle of the PWM waveform and by varying the duty cycle we control the average load voltage. Figure 9.2 shows the average voltage for different values of the duty cycle.

[Figure 9.2 Average voltage (shown as dashed line) supplied to a load]

â—? 224


Programming with STM32 Nucleo Boards

CHAPTER 10 • I2C BUS INTERFACE 10.1 • Overview

The I2C (or I2C) bus is commonly used in microcontroller based projects. In this Chapter we shall be looking at the use of this bus with our Nucleo-L476RG board. The STM32L476RG processor includes three I2C bus interfaces. The aim is to make the reader familiar with the I2C bus library functions and to show how they can be used in a real project. Before looking at the details of the project it is worthwhile to look at the basic principles of the I2C bus. 10.2 • The I2C Bus

I2C bus is one of the most commonly used microcontroller communication protocols for communicating with external devices such as sensors and actuators. The I2C bus is a single master, multiple slave bus and it can operate at standard mode: 100 Kbit/s, full speed: 400 Kbit/s, fast mode: 1 Mbit/s, and high speed: 3,2 Mbit/s. The bus consists of two open-drain wires, pulled-up with resistors: SDA: data line SCL: clock line Figure 10.1 shows the structure of an I2C bus with one master and three slaves.

[Figure 10.1 I2C bus with one master and three slaves]

Communication is initiated by the master which sends a START bit. This alerts all the slaves that some data is coming on the bus and all the slaves listen on the bus. After the start bit, 7 bits of unique slave address is sent. Each slave device on the bus has its own address and this ensures that only the addressed slave communicates on the bus at any time to avoid any collisions. The last sent bit is read/write bit such that if this bit is 0, it means that the master wishes to write to the bus (e.g. to a register of a slave), if this bit is a 1, it means that the master wishes to read from the bus (e.g. from the register of a slave). The data is sent on the bus with the MSB bit first.

● 232


Chapter 10 ● I2C BUS INTERFACE

10.3 • Mbed I2C Bus Functions

The Mbed I2C bus functions are as follows: frequency: read: write: start: stop:

This This This This This

function function function function function

sets the frequency of the I2C interface reads from an I2C interface writes to an I2C interface creates a start condition on the I2C bus creates a stop condition on the i2C bus

When reading and writing to the bus we have to specify the device address, register address and the number of bytes. On the Nucleo-L476RG board we have three I2C interfaces. The default one with the Mbed pin names I2C_SCL and I2C_SDA is connected to PB_8 (pin 3 on morpho connector CN10) and PB_9 (pin 5 on morpho connector CN10) respectively (see link: https://os.mbed.com/platforms/ST-Nucleo-L476RG/) 10.4 • PROJECT 22 – Port Expander 10.4.1 • Description

A simple project is given in this section to show how the I2C functions can be used in Mbed programs. In this project an I2C bus compatible Port Expander chip (MCP23017) is used to give additional 16 I/O ports to the Nucleo-L476RG board. This is useful in some applications where a large number of I/O ports may be required. In this project an LED is connected to MCP23017 port pin GPA0 (pin 21) and the LED is flashed ON and OFF every second. A 330 ohm current limiting resistor is used in series with the LED. 10.4.2 • The Aim

The aim of this project is to show how the I2C bus can be used in Nucleo-L476RG based projects. 10.4.3 • Block Diagram

The block diagram of the project is shown in Figure 10.2.

● 233


Chapter 11 ● USING THE EXPANSION BOARDS

CHAPTER 11 • USING THE EXPANSION BOARDS 11.1 • Overview

As described briefly in Chapter 2, there are a large number of Expansion Boards that can be used with the STM32 Nucleo development boards. The expansion boards plug on top of the Nucleo boards through the Arduino connectors. Some boards include sensors (e.g. magnetometer, accelerometer, temperature sensor, and humidity sensor), some include electric motor drivers, some provide Wi-Fi capabilities to the Nucleo boards, some provide industrial outputs and so on. The expansion boards are equipped with standardized interconnections, such as • An Arduino Uno R3 connector, or • A Morpho connector for a higher level of connectivity STM32 Nucleo expansion boards carry all the required components to evaluate various ST development boards, and also help to speed up the project development cycle by providing tested hardware and software solutions. In this Chapter we shall be using some of these expansion boards in simple projects. The aim here is not to develop complex projects, but to show how these boards can be used with the Nucleo-L476RG development board in projects. More information on the Nucleo expansion boards can be obtained from the following site: http://www.st.com/en/evaluation-tools/stm32-nucleo-expansion-boards.html? querycriteria=productId=SC1971 All of the pictures of Expansion Boards in this Chapter are the copyright of STMicroelectronics and have been used here with their written permission: ©STMicroelectronics. Used with permission. 11.2 • Industrial Digital Output Expansion Board (X-NUCLEO-OUT01A1)

As discussed briefly in Chapter 2 (Figure 2.14) this is an industrial output expansion board based on the ISO8200BQ chip. This board provides 8 outputs with status LED indicators. The operating voltage is 10.5V to 33V, and the maximum output current per channel is 700 mA. The board uses the ISO8200BQ galvanic isolated octal power solid state relay, making it possible for use in power control applications. It contains two independent galvanic isolated voltage domains with GND protection, over-voltage and under-voltage shutdown and over-temperature protection. ISO8200BQ can drive any kind of load with one side connected to ground. 8 screw type output connectors are provided on the board for making connections to external world. Figure 11.1 shows the PCB layout of the board. The ISO8200BQ chip is placed in the middle of the board. The screw type output connector (J5) is at the bottom of the board. At the top of the board a two-terminal screw connector (J2) is provided for applying external digital voltage (7V – 12V) should it be necessary, for example in standalone battery operations. An external 10.5V to 33V power supply must be connected to the two-terminal connector J1, placed at the bottom right of the board. A jumper selection (J4) is provided next to the

● 243


Programming with STM32 Nucleo Boards

chip for selecting the operation mode between SYNC and DIRECT as we shall see later. For DIRECT access mode jumper J4 should be connected to GND, and for SYNC access it should be connected to +3.3V.

[Figure 11.1 PCB Layout of the industrial digital output expansion board]

Before using the board it is important to understand how the ISO8200BQ solid state relay chip operates. Figure 11.2 shows the block diagram of the ISO8200BQ chip. The functional block diagram of the industrial digital output expansion board is shown in Figure 11.3. On the left we can see 8 inputs labelled IN1 to IN8 and on the right hand side one of the 8 outputs is shown. IN1 to IN8 are the driving signals for the corresponding output channels. 10.5V to 30V external voltage is applied to the chip through its high voltage Vdd pin. Vcc is the external low voltage logic power pin. We can also see control pins labelled SYNC, LOAD, OUT_EN, and FAULT. The FAULT pin is an open-drain active low fault indication pin and is connected to an LED on the expansion board.

â—? 244


Programming with STM32 Nucleo Boards

Index A Absolute current rating 68 Absolute voltage rating 68 Accelerometer 35, 261 ADC 74 AHB1 64 AHB2 64 Alternate function register 65 AnalogIn 182 AnalogOut 216 Analog temperature sensor 180 APB1 64 APB2 64 Arduino Uno connector 243 ARM mbed 43 Attach 157 Attach_us 157 Atmospheric pressure 262 Average voltage 224 B Baud rate 192 Bluetooth 26 BOOT0 62 Brushed motor 256 Brushless DC motor 32 BSRRH 102 BSRRL 102 Button B1 24 Buzzer 206 C CN1 17 CN2 17 Common anode 139 Common cathode 138 Configuration tab 84 Cortex-A 59 Cortex-M 58 Cortex-R 58 CRC 61 Crystal oscillator 72 D DAC 74, 216 Data bits 192 Data register 64 Debug 199 Demo software 24 Detach 157 Dice 126 DMIPS 61 Duty cycle 223

â—? 286

E E5V 19, 20 Echo 195, 207 EEMBC 60 Embedded Workbench 43 Event counter 150 Expansion board 25, 243 External clock source 72 EWARM 43 F Flashing LED 106 Frequency 233 G Gesture detection 41 GPIO 61, 64 GPIO library 100 GPIOx_AFRH 65 GPIOx_AFRL 65 GPIOx_BSRR 64 GPIOx_IDR 64 GPIOx_LCKR 65 GPIOx_MODER 64 GPIOx_ODR 64 GPIOx_OSPEEDR 64 GPIOx_OTYPER 64 H HAL_Delay 90 HAL_GPIO_EXTI_Callback 102, 154 HAL_GPIO_EXTI_IRQHandler 102, 153 HAL_GPIO_LockPin 101 HAL_GPIO_ReadPin 101 HAL_GPIO_TogglePin 101 HAL_GPIO_WritePin 101 HAL_I2C_Master_Transmit 240 HD44780 169 Handshake 192 HSE 72 Humidity 262 HyperTerm 192 I I2C 61, 232 I2C_Address 240 Industrial I/O 40 Internal block diagram 61 Internal clock source 73 Interrupt 75 IODIRA 235 IODIRB 235 IP address 267 ISO8200BQ 244 J Jumper JP1 20 Jumper JP5 20 Jumper JP6 21


STM32 NUCLEO BOARDS Dogan Ibrahim

Prof Dr Dogan Ibrahim has a BSc degree in electronic engineering, an MSc degree in automatic control engineering, and a PhD degree in digital signal processing. He has worked in many industrial organizations before he returned to academic life. Prof Ibrahim is the author of over 60 technical books and over 200 technical articles on microcontrollers, microprocessors, and related fields. He is a Chartered electrical engineer and a Fellow of the Institution of Engineering Technology.

ISBN 978-1-907920-68-4

STM32 Nucleo family of processors are manufactured by STMicroelectronics. These are low-cost ARM microcontroller development boards. This book is about developing projects using the popular Nucleo-L476RG development board. In the early Chapters of the book the architecture of the Nucleo family is briefly described. Software development tools that can be used with the Nucleo boards such as the Mbed, Keil MDK, TrueSTUDIO, and the System Workbench are described briefly in later Chapters. The book covers many projects using most features of the NucleoL476RG development boards where the full software listings for Mbed and System Workbench are given for every project. The projects range from simple flashing LEDs to more complex projects using modules and devices such as GPIO, ADC, DAC, I2C, LCD, analog inputs and others. In addition, several projects are given using the Nucleo Expansion Boards, including popular expansion boards such as: solid-state relay, MEMS and environmental sensors, DC motor driver, Wi-Fi, and stepper motor driver. These Expansion Boards plug on top of the Nucleo development boards and simplify the task of project development considerably. Features of this book • Learn the architecture of the STM32 microcontrollers • Learn how to use the Nucleo-L476RG development board in projects using Mbed and System Workbench Toolchains

Elektor International Media BV

www.elektor.com

LEARN DESIGN

• Learn how to use the Nucleo Expansion Boards with the Nucleo development boards

PROGRAMMING WITH STM32 NUCLEO BOARDS ● DOGAN IBRAHIM

PROGRAMMING WITH

PROGRAMMING WITH

STM32 NUCLEO BOARDS

Dogan Ibrahim LEARN DESIGN SHARE

SHARE

LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHAR GN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHAR


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.