You are on page 1of 35

MCU Programming using mbed

An open source platform for IoT


What is mbed?
 mbed is an open source platform for developing embedded
systems based on ARM Cortex®-M microprocessor
Microcontroller and Toolchain Portability
Hardware Abstraction Layer C Libraries and project exports
Components Libraries
 Write a component library once and get supported on multiple
mbed platforms.
 Implement the mbed HAL once and immediately support thousands
of components.
Open Source Project
Open sourced Feb. 2015, already getting momentum

 107 Contributors (github stats track only its users)


 149 Pull Requests
 112 Followers
 108 mailing list members
Example Application
LIS302 Accelerometer

 Simple user friendly C++ for the user


 Component-based approach
 The implementation does not reference
any MCU register, but only the mbed API
SDK Architecture
Your code

Developed
by mbed.org
or its
contributors

Device vendor’s
library

Device register
level
Library Architecture
Design Overview
The mbed library provides abstractions for the microcontroller (MCU)
hardware (in particular drivers for the MCU peripherals) and it is divided in the
following software layers and APIs:

The code you write here


can be used on any mbed
enabled platform
Library Architecture
 Example for a STM32 device, initialize a led:
DigitalOut led(LED1); Mbed.org high level library

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; STM32 library


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; for peripheral
… …
GPIO_Init(GPIOD, &GPIO_InitStructure); configuration

MCU register
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
… …
access
GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2));
GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));
… …
}
ARM CMSIS for
ARM CMSIS library for core registers core register
configuration
C++ in the SDK

 Lightweight wrapper  Verbose


 Concise  Harder to understand
 Stable API  API may change
 14.2k flash / 0.5k RAM  11.1k flash / 0.4k RAM
Prerequisites:
 Mbed enabled Nucleo board
 USB cable
 ST-link drivers (available here:
http://www.st.com/web/catalog/tools/FM146/CL1984/SC724/SS1
677/PF251168)
 Serial terminal (i.e. Putty, RealTerm, HyperTerminal, etc…)
 C++ or at last C programming notions
 (optional) ST-Link Utility
 (optional) any sensor/actuator to add more fun!
Register and login to mbed.org
After registration you can access to the compiler
Online compiler
Add a new device to start programming!
Online Compiler
Choose you platform
Choose NUCLEO-F401RE and add it to compiler
Platform Characteristics:
https://www.youtube.com/watch?v=FntTelSoqSk
Platform Characteristics II
 On-board ST-LINK/V2-1
debugger/programmer
with SWD connector
 Selection-mode
switch to use the kit
as a standalone ST-
LINK/V2-1
 USB re-enumeration
capability: three different
interfaces supported on
USB
 Virtual Com port
 Mass storage (USB
Disk drive) for
drag'n'drop
programming
 Debug port
Create a new project from template
Right click on my Projects and choose New Project, then select “Blinky LED test for the
ST Nucleo boards”
View library documentation
If documentation is not available you can convert the mbed fil into a library
and have a look at header files
Look at the code
 #include "mbed.h"

DigitalOut myled(LED1); Object myled

int main() {
while(1) {
myled = 1; // LED is ON Operator overloading
wait(0.2); // 200 ms (look at the definition,
myled = 0; // LED is OFF ctrl + click)
wait(1.0); // 1 sec
}
}


The MCU can never exit from the Main function
Program your board
Connect the board to your PC

• Compilation successful -> binary file downloaded


• Copy the “projectname.bin” file from your download folder to the
“NUCLEO” drive
• If no Nucleo drive is detected, install ST-Link Driver
Print to console
 Create Serial Object (TX and RX pins are defined):
 Serial pc(SERIAL_TX, SERIAL_RX);
 Standard Baud Rate is 9600bps
 Use the Object with Printf:
 pc.printf("Hello World\r\n");
 Standard printf (i.e. printf ("floats: %4.2f, 3.1416); works)
 scanf also works

 On the Nucleo Board, one serial port is redirected as virtual


com port trough the debugger
Print to console II
 Serial pc(SERIAL_TX, SERIAL_RX);
DigitalOut myled(LED1);
int main() {
int i = 0;
while(1) {
myled = 1; // LED is ON
wait(0.2); // 200 ms
myled = 0; // LED is OFF
wait(1.0); // 1 sec
pc.printf("Hello World: %d \r\n ", i);
pc.scanf ("%d",&i); // read an Int
}
}

 Compile and download the program


 Detect your virtual port:
 Device Manager
 STM32 properties -> Virtual Com Port
 Open terminal (i.e. Putty COM23 – Baud 9600)

 What you notice? Is led blinking?


RTC to track time
 #include "mbed.h"

DigitalOut myled(LED1);

int main() {

printf("RTC example\n");
set_time(1429284734); // Set RTC time to Fri, 17 Apr 2015 15:32:14 UTC
printf("Date and time are set.");

while(1) {
time_t seconds = time(NULL);
printf("Time as a basic string = %s\r\n", ctime(&seconds));
myled = !myled;
wait(1);
}
}

RTC autonomously keep track of the elapsed time


Nested Vector Interrupt Controller NVIC
Nested Vector Interrupt Controller NVIC

 Nested Interrupt: If a interrupt


request (IRQ) with higher
priority is raised, it is served first

 Tail chaining: for nested ISR does


not restore all saved registers
from the stack.
 Stack pop pre-emption: If
another exception occurs during
the unstacking process of an
exception, the processor
abandons the stack Pop
Welcome Interrupts
 #include "mbed.h"

InterruptIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);

float delay = 1.0; // 1 sec

void pressed() { // changes the delay frequency Interrupt is automatically


if (delay == 1.0)
called when the button
delay = 0.2; // 200 ms
else event is detected
delay = 1.0; // 1 sec
}

int main()
{
mybutton.fall(&pressed); // Attach interrupt on falling edge
while (1) {
myled = !myled;
wait(delay);
}
}

Periodic interrupt
 #include "mbed.h"

Ticker toggle_led_ticker; // Ticker can be seen as a periodic interrupt


DigitalOut led1(LED1);

void toggle_led() {
led1 = !led1;
}

int main() {
// Init the ticker with the address of the function (toggle_led) to be
attached and the interval (100 ms)
toggle_led_ticker.attach(&toggle_led, 0.1);
while (true) {
// Do other things...
}
}

Serial using Interrupts
 #include "mbed.h"

Serial pc(SERIAL_TX, SERIAL_RX);


DigitalOut myled(LED1);

void callback() {
// Note: you need to actually read from the serial to clear the RX interrupt
int i = 0;
pc.scanf("%d",&i);
pc.printf("Hello Interrupt: %d \r\n ", i);
}

int main() {
pc.attach(&callback);
Interrupt does not block main
while(1) { execution and is called only
myled = 1; // LED is ON when new data on serial port
wait(0.2); // 200 ms are present
myled = 0; // LED is OFF
wait(1.0); // 1 sec
}
}
Analog to Digital Conversion:
 Connect the potentiometer to the board:
 10K potentiometer
 External pin connected to 3.3V and GND
 Central pin connected to A0
Analog to Digital Converter
 #include "mbed.h"

AnalogIn analog_value(A0);

DigitalOut led(LED1);

int main() {
float meas;
printf("\nAnalogIn example\n");
while(1) {
meas = analog_value.read(); // Converts the analog input value (value from 0.0 to 1.0)
meas = meas * 3300; // Change the value to be in the 0 to 3300 range
printf("measure = %.0f mV\n", meas);
if (meas > 2000) { // If the value is greater than 2V then switch the LED on
led = 1;
}
else {
led = 0;
}
wait(0.2); // 200 ms
}
}
Pulse Width Modulation
 #include "mbed.h"

InterruptIn my_button(USER_BUTTON);
PwmOut my_pwm(LED1);

void pressed() {
if (my_pwm.read() == 0.25) {
my_pwm.write(0.75);
}
else {
my_pwm.write(0.25);
}
}

int main()
{
// Set PWM
my_pwm.period_ms(10);
my_pwm.write(0.25); //Set the Duty cycle

// Set button
my_button.fall(&pressed);
while (1) {

} Led change intensity since period is too small


}

to be detected by human eye
Project:
 Wait for button pressed
 When button is pressed start ADC acquisition at 5Hz using
Ticker
 Change led intensity (using PWM) according to ADC value
 When Button is pressed stop acquisition
 Send via serial port for how long the acquisition lasted
 Tip you can use RTC
Using the Compiler - Offline
Using the Compiler – Offline
 Export from online IDE
 Use offline IDE/command line tools (make)
 Supported: uVision, IAR, make (various), CodeRed …

c:\work\temp> unzip ~/Downloads/blinky_gccarm_lpc1768.zip


inflating: blinky/main.cpp
inflating: blinky/.hgignore
inflating: blinky/Makefile
………

c:\work\temp> cd blinky\

[hg:default] c:\work\temp\blinky> make


arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -c -Os -fno-common -fmessage-length=0 -Wall -
fno-exceptions -ffunction-sections -fdata-sections -DTARGET_LPC1768 -DTARGET_M3 ………
………
arm-none-eabi-objcopy -O binary blinky.elf blinky.bin

[hg:default] c:\work\temp\blinky> move blinky.bin e:

You might also like