LPC812 MAX Experiment: Interrupts

Experiment: Interrupts

In this experiment you will learn how to incorporate interrupts in your program. Interrupts are a powerful concept in embedded programming. It is a way to interrupt the normal program execution flow to service something else quickly. This “something else” is typically a peripheral block that needs to be serviced or it is an external event that needs attention/a reaction.

There is a functional block in the LPC800 series that is called the Nested Vectored Interrupt Controller (NVIC). It is an integral part of the Cortex-M0+ core. The NVIC can be regarded as a peripheral block, but a special one. It is programmed/setup via registers, just like any other peripheral. It supports 32 interrupt sources and there are four programmable priority levels. Individual interrupts can be masked (i.e., disabled) in the NVIC. It is also possible to generate an interrupt via software - writing in a special register will trigger the specified interrupt.

Normally it is good system design practice to keep the execution time in the interrupts as short as possible. The actions that are needed immediately are done in the interrupt service routine (ISR). Actions that can wait should be scheduled for later execution in the normal program flow. If it is not possible to keep execution time in an ISR short, nested interrupts can be used. Nested interrupts means that an interrupt can interrupt another interrupt if it has higher priority.

1) Hardware

In this lab you will need:

  • 1x breadboard
  • 1x push-button
  • 1x 330 ohm resistor
  • cables

Mount the components on the breadboard and connect the breadboard to the LPC812 as show in the image below.

Breadboard Setup

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

Schematic Namembed Pin NameArduino Shield AliasDescription
PIO0_0P0_0D0Push-button
PIO0_17-GREENP0_17N/ALED_GREEN

1) Description

In this experiment an interrupt will be generated from a GPIO input using the breadboard setup above and the green onboard LED (part of the RGB LED). The mbed library has a InterruptIn class for GPIO interrupts:

Import library

Public Member Functions

InterruptIn (PinName pin)
Create an InterruptIn connected to the specified pin.
void rise (void(*fptr)(void))
Attach a function to call when a rising edge occurs on the input.
template<typename T >
void rise (T *tptr, void(T::*mptr)(void))
Attach a member function to call when a rising edge occurs on the input.
void fall (void(*fptr)(void))
Attach a function to call when a falling edge occurs on the input.
template<typename T >
void fall (T *tptr, void(T::*mptr)(void))
Attach a member function to call when a falling edge occurs on the input.
void mode (PinMode pull)
Set the input pin mode.
void enable_irq ()
Enable IRQ.
void disable_irq ()
Disable IRQ.

Using that class it is very simple to handle interrupts:

main.cpp

#include "mbed.h"

InterruptIn event(D0);

void trigger() {
     // add code to blink the LED
}
 
int main()
{
    // Register the handler for falling edges
    event.mode(PullUp);
    event.fall(&trigger);
    while(1) {
        ;
    }
}

Complete the example above and test it.

Information

Note that due to contact bouncing (inside the push-button) sometimes several edges will be detected when the push-button is pressed. In this experiment this effect is ignored but to in a real system contact bounce must be handled properly

By moving the button detection to an interrupt handler it frees up the loop in main to do other stuff.

If you need to do time consuming things (like for example printing something) it can and probably should be moved to the main loop instead. If the time consuming task is done inside the interrupt then it could potentially make the system unresponsive.

The example below shows what happens if the interrupt function takes too long to end. The red LED will stop blinking while the button is pressed.

// Declare variables

void trigger() {
    greenLED = 0;
    while (button) {
    }
    greenLED = 1;
}

int main() {
    event.mode(PullUp);
    event.fall(&trigger);

    // Initialize variables
    greenLED = 1;
    redLED = 1;
    
    while(1) {
        redLED = !redLED;
        wait(0.1);
    }
}

Try to fix the problem with the code above. One solution could be to move the code that turns off the green LED into the main loop. Another solution could be to use one extra InterruptIn.

2) Hardware

This experiment will only use the onboard RGB LED.

2) Description

In this experiment you will use time as a trigger instead of the GPIO. The mbed library has a Ticker class:

Import library

Public Member Functions

void attach (void(*fptr)(void), float t)
Attach a function to be called by the Ticker , specifiying the interval in seconds.
template<typename T >
void attach (T *tptr, void(T::*mptr)(void), float t)
Attach a member function to be called by the Ticker , specifiying the interval in seconds.
void attach_us (void(*fptr)(void), unsigned int t)
Attach a function to be called by the Ticker , specifiying the interval in micro-seconds.
template<typename T >
void attach_us (T *tptr, void(T::*mptr)(void), unsigned int t)
Attach a member function to be called by the Ticker , specifiying the interval in micro-seconds.
void detach ()
Detach the function.

Static Public Member Functions

static void irq (uint32_t id)
The handler registered with the underlying timer interrupt.

With the ticker it is possible to register a function that will be called at a specific rate like this:

main.cpp

#include "mbed.h"

Ticker timer;

void event() {
     // add code to blink the LED
}
 
int main()
{
    // Request the timer function to be called every 5 seconds
    timer.attach(&event, 5);
    while(1) {
        ;
    }
}

Complete the example above and test it. Add two more timers and let each timer control a separate color on the RGB LED.

Solution(s)

Import programlpc812_exp_solution_interrupts

Solutions for the Interrupts experiments for LPC812 MAX


1 comment on LPC812 MAX Experiment: Interrupts:

30 Jun 2015

The library is missing

Please log in to post comments.