LPC812 MAX Experiment: Digital Out

Experiment: Control a LED

In this first experiment you will learn how to control the I/O pins of the LPC8xx microcontroller. More specifically you will learn how to control a LED.

Hardware

This lab uses only the onboard RGB LED so no external components are needed.

1) Description

The schematics tells us that the RGB LED is connected to the following pins:

  • PIO0_16 to the BLUE LED
  • PIO0_17 to the GREEN LED
  • PIO0_7 to the RED LED

The pins are specified in the mbed library with the actual pin names as well as some useful aliases:

Pin Namembed Standard AliasLPC812 Specific Alias
P0_16LED1LED_BLUE
P0_17LED2LED_GREEN
P0_7LED3LED_RED

The mbed library has a DigitalOut class to simplify using the GPIOs:

Import library

Public Member Functions

DigitalOut (PinName pin)
Create a DigitalOut connected to the specified pin.
void write (int value)
Set the output, specified as 0 or 1 (int)
int read ()
Return the output setting, represented as 0 or 1 (int)
DigitalOut & operator= (int value)
A shorthand for write()
operator int ()
A shorthand for read()

All three LEDs are active low meaning that they will turn on when the respective LPC812 pin is low. The example below demonstrates how to use the different alias to create instances of DigitalOut to blink the LEDs.

main.cpp

#include "mbed.h"

DigitalOut myled1(P0_16);
DigitalOut myled2(LED2);
DigitalOut myled3(LED_RED);

int main() {
    //Turn all LEDs off
    myled1 = 1;  //LED1 is active low, turn it off
    myled2 = 1;  //LED2 is active low, turn it off
    myled3 = 1;  //LED3 is active low, turn it off

    //Enter forever loop
    while(1) {
        myled3 = 1;  //Turn LED3 off
        myled1 = 0;  //Turn LED1 on
        wait(0.2);   //Wait 200 ms
        myled1 = 1;  //Turn LED1 off
        myled2 = 0;  //Turn LED2 on
        wait(0.2);   //Wait 200 ms
        myled2 = 1;  //Turn LED2 off
        myled3 = 0;  //Turn LED3 on
        wait(0.2);   //Wait 200 ms
    }
}

Setting the DigitalOut to 0 to turn the LED on might be confusing and it is not good practice to keep writing comments on all lines in the program just to keep track of the LEDs. An alternative might be to create an LED class like this:

LED.h

#ifndef LED_H
#define LED_H

class LED {
public:

    enum ActiveLevel {
        ActiveHigh = 0,
        ActiveLow = 1
    };

    /** Create a LED controller
     *
     */
    LED(PinName pin, ActiveLevel level);

    /** Turn the LED on
     */
    void on();

    /** Turn the LED off
     */
    void off();

    /** Turn the LED on/off.
     *
     *  @param turnOn Turns the LED on if true, off if false
     */
    void setState(bool turnOn);

private:

    DigitalOut _out;
    ActiveLevel _level;    
};

#endif

LED.cpp

#include "mbed.h"
#include "LED.h"

LED::LED(PinName pin, ActiveLevel level) : _out(pin), _level(level)
{
  off();
}

void LED::on()
{
  if (_level == ActiveHigh) {
    _out = 1;
  } else {
    _out = 0;
  }
}

void LED::off()
{
  if (_level == ActiveHigh) {
    _out = 0;
  } else {
    _out = 1;
  }
}

void LED::setState(bool turnOn)
{
  if (turnOn) {
    on();
  } else {
    off();
  }
}

With the new LED class and better variable names the code looks much cleaner:

main.cpp

#include "mbed.h"
#include "LED.h"

LED blueLED(P0_16, LED::ActiveLow);
LED greenLED(LED2, LED::ActiveLow);
LED redLED(LED_RED, LED::ActiveLow);

int main() {
    //Turn all LEDs off
    blueLED.off();
    greenLED.off();
    redLED.off();

    //Enter forever loop
    while(1) {
        redLED.off();
        blueLED.on();
        wait(0.2);   //Wait 200 ms
        blueLED.off();
        greenLED.on();
        wait(0.2);   //Wait 200 ms
        greenLED.off();
        redLED.on();
        wait(0.2);   //Wait 200 ms
    }
}

2) Description

The programs in the previous step were controlled by delays. There are more sophisticated ways to control the LED flashing, for example by using the mbed ticker functionality. More information can be found here. The ticker functionality is a prime example of the powerful mbed framework. Advanced functionality can quickly be incorporated into your application by just instantiating an object.

Test the code below and experiment with different flash patterns.

main.cpp

#include "mbed.h"
#include "LED.h"

Ticker tickObject;
LED blueLED(P0_16, LED::ActiveLow);
LED greenLED(LED2, LED::ActiveLow);
LED redLED(LED_RED, LED::ActiveLow);

void flashHandler(void) {
    static int ledState = 0;
 
    //Turn all LEDs off
    blueLED.off();
    greenLED.off();
    redLED.off();
 
    switch (ledState) {
        case 0: blueLED.on();  break;
        case 1: greenLED.on(); break;
        case 2: redLED.on();   break;
        default: ledState = 0;
    }
    ledState++;
    if (ledState >= 3)
        ledState = 0;
}

int main() {
    //Turn all LEDs off
    blueLED.off();
    greenLED.off();
    redLED.off();

    //Repeatedly call flashHandler(), once every 200ms
    tickObject.attach(&flashHandler, 0.2);
    
    //Enter forever loop
    while(1) {
        ;    //do something useful while LED flashing is handled in the background
    }
}

There is also a timeout functionality that can be used, for example if varying time intervals are needed between calling flashHandler(). The timeout must then be restarted after every call to flashHandler().


Please log in to post comments.