Toggle Highlight Highlight Colour Function Info
GPIO Info
ADC Info
DAC Info
PWM Info
I2C Info
UART Info
CAN Info
Other Help topics
Using LPC17xx interrupts

Pin Function 3 Pin Function 2 Pin Function 1 Pin Function 0 Pin Number Port Number MBed Pin   MBed Pin Port Number Pin Number Pin Function 0 Pin Function 1 Pin Function 2 Pin Function 3
Reserved AD0.6 RXD0 GPIO Port 0.3 3 0 USB RX MBed Board USB TX 0 2 GPIO Port 0.2 TXD0 AD0.7 Reserved
(Gnd) - - 1 40 - - 3.3v Regulated (VOUT)
4.5v-9.0v (VIN) - - 2 39 - - 5.0v USB out (VU)
1.8v-3.3v Battery for RTC (VB) - - 3 38 - - USB D- from connector (IF-)
External reset (nR) - - 4 37 - - USB D+ from connector (IF+)
MAT2.3 MOSI1 I2STX_SDA GPIO Port 0.9 9 0 5 36 - - Ethernet RD- (From DP83848)
MAT2.2 MISO1 I2STX_WS GPIO Port 0.8 8 0 6 35 - - Ethernet RD+ (From DP83848)
MAT2.1 SCK1 I2STX_CLK GPIO Port 0.7 7 0 7 34 - - Ethernet TD- (From DP83848)
MAT2.0 SSEL1 I2SRX_SDA GPIO Port 0.6 6 0 8 33 - - Ethernet TD+ (From DP83848)
SDA1 TXD3 RD1 GPIO Port 0.0 0 0 9 32 0 30 GPIO Port 0.30 USB_D- Reserved Reserved
SCL1 RXD3 TD1 GPIO Port 0.1 1 0 10 31 0 29 GPIO Port 0.29 USB_D+ Reserved Reserved
MOSI MOSI0 DCD1 GPIO Port 0.18 18 0 11 30 0 4 GPIO Port 0.4 I2SRX_CLK RD2 CAP2.0
MISO MISO0 CTS1 GPIO Port 0.17 17 0 12 29 0 5 GPIO Port 0.5 I2SRX_WS TD2 CAP2.1
SCK SCK0 TXD1 GPIO Port 0.15 15 0 13 28 0 10 GPIO Port 0.10 TXD2 SDA2 MAT3.0
SSEL SSEL0 RXD1 GPIO Port 0.16 16 0 14 27 0 11 GPIO Port 0.11 RXD2 SCL2 MAT3.1
CAP3.0 I2SRX_CLK AD0.0 GPIO Port 0.23 23 0 15 26 2 0 GPIO Port 2.0 PWM1.1 TXD1 Reserved
CAP3.1 I2SRX_WS AD0.1 GPIO Port 0.24 24 0 16 25 2 1 GPIO Port 2.1 PWM1.2 RXD1 Reserved
TXD3 I2SRX_SDA AD0.2 GPIO Port 0.25 25 0 17 24 2 2 GPIO Port 2.2 PWM1.3 CTS1 Reserved
RXD3 AOUT AD0.3 GPIO Port 0.26 26 0 18 23 2 3 GPIO Port 2.3 PWM1.4 DCD1 Reserved
AD0.4 VBUS Reserved GPIO Port 1.30 30 1 19 22 2 4 GPIO Port 2.4 PWM1.5 DSR1 Reserved
AD0.5 SCK1 Reserved GPIO Port 1.31 31 1 20 21 2 5 GPIO Port 2.5 PWM1.6 DTR1 Reserved
CAP1.0 PWM1.1 USB_UP_LED GPIO Port 1.18 18 1 LED1 LED4 1 23 GPIO Port 1.23 MCI1 PWM1.4 MISO0
SCK0 PWM1.2 MCI0 GPIO Port 1.20 20 1 LED2 LED3 1 21 GPIO Port 1.21 MCABORT PWM1.3 SSEL0
Pin Function 3 Pin Function 2 Pin Function 1 Pin Function 0 Pin Number Port Number MBed Pin   MBed Pin Port Number Pin Number Pin Function 0 Pin Function 1 Pin Function 2 Pin Function 3

GPIO (General Purpose Input/Output)
Uses:
  • General purpose I/O.
  • Controlling LEDs.
  • Interrupt on input level/edge.
  • Wake CPU with external events.
Pin Functions
GPIOx.y General Purpose Input/Output (on port x pin y)
Code
Important headers:
Interrupt defines:
  • EINT3_IRQn - External interrupt 3 (Shared with GPIO interrupts).
Useful functions:
  • Set direction of pins to input or output:
            void GPIO_SetDir (uint8_t portNum, uint32_t bitValue, uint8_t dir)
  • Set pin outputs to high:
            void GPIO_SetValue (uint8_t portNum, uint32_t bitValue)
  • Set pin outputs to low:
            void GPIO_ClearValue (uint8_t portNum, uint32_t bitValue)
  • Read input from GPIO port:
            uint32_t GPIO_ReadValue (uint8_t portNum)
See: Public GPIO functions.
Example code (GPIO Output): #include "lpc_types.h"
#include "lpc17xx_gpio.h"

// A simple program to move a lit LED back and forth on the four onboard mbed LEDs.
void main (void)
{
   // The LPC1768 port 1 pin masks for the individual mbed onboard LEDs.
   uint32_t led_mask[4] = {1 << 18, 1 << 20, 1 << 21, 1 << 23};
   
   // The LPC1768 port 1 pin mask for all the mbed onboard LEDs.
   uint32_t all_leds_mask = led_mask[0] | led_mask[1] | led_mask[2] | led_mask[3];
   
   // Set the direction of the pins on Port 1 for the mbed onboard LEDs to output.
   GPIO_SetDir(1, all_leds_mask, 1);
   
   // The number of the LED currently lit.
   uint8_t led_number = 0;
   
   // The direction the lit LED is moving: 0 - left to right, 1 - right to left.
   uint8_t direction_backwards = 0;
   
   // Loop forever.
   while (1)
   {
      // Turn off all LEDs.
      GPIO_ClearValue(1, all_leds_mask);
      
      // Turn on the current LED.
      GPIO_SetValue(1, led_mask[led_number]);
      
      if (!direction_backwards)
      {
         // If moving forwards increment led_number until it is the last, then reverse direction.
         led_number++;
         if (led_number >= 3)
         {
            direction_backwards = 1;
         }
      }
      else
      {
         // If moving backwards decrement led_number until it is the first, then reverse direction.
         led_number--;
         if (led_number <= 0)
         {
            direction_backwards = 0;
         }
      }
      
      // Count to 2 million to generate a crude delay.
      uint32_t cycleNo = 0;
      while (cycleNo < 2000000)
      {
         cycleNo++;
      }
   }
}
I2C (Inter-Integrated Circuit bus/protocol)
Uses:
  • Communication with external I2C devices e.g. LCD displays, IO expanders.
Notes:
  • On the University of York HostBoard the LCD, keypad, clock display, EEPROM and IO expander are all on an I2C bus connected to pins 9 and 10 of the mbed.
  • Even though SDA1 and SCL1 are on Port 0 Pins 0 and 1 they are connected to I2C device 1 not device 0.
  • If you are using polling to handle the I2C transfers and your program freezes on starting a transfer you are probably using the wrong I2C device.
  • When setting up the I2C device you are using make sure you do not set the rate faster than other devices on the bus can handle (check datasheets, 100kHz is good for the University of York HostBoard bus).
  • On the University of York HostBoard there is a PCF Int / I2C Int line connected to the two IO expanders' interrupt pins which is normally high and is pulled low when any of their inputs are changed. The PCF Int / I2C Int line can be connected to mbed pin 15 by plutting a jumper on the I2C Int header (under the keypad), once this is done you can interrupt on an IO expander input change by enabling a falling edge GPIO interrupt on mbed pin 15.
  • When setting up the PCF2119X LCD display driver over I2C you MUST set up things like the voltage multipliers and LCD voltage using the extended intruction set (even though the datasheet does not mention this in it's example) because if you do not contrast will be so low that nothing will be visible on the display.
  • When an IO expander HIGH pin is connected to an IO expander LOW pin (like when a button is pressed on the hex keypad) the HIGH pin will be pulled LOW, not the other way round like you might expect.
I2C addresses:
IC Name IC Description 8 bit address 7 bit address
PCF8574 IO expander 0x40 0x20
PCF8574 IO expander (keypad) 0x42 0x21
SAA1064 4 digit LED driver 0x70 0x38
PCF2119X LCD display driver 0x76 0x3B
24AA256 EEPROM 0xA0 0x50
Pin Functions
SDAx I2C Serial DAta for I2C device x
SDAx I2C Serial CLock for I2C device x
Code
Important headers:
Device struct defines:
  • LPC_I2C1 - I2C device 1.
  • LPC_I2C2 - I2C device 2.
Interrupt defines:
  • I2C1_IRQn - I2C device 1 interrupt.
  • I2C2_IRQn - I2C device 2 interrupt.
Example code (Polling hex keypad): #include "LPC17xx.h"
#include "lpc_types.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_i2c.h"

#define KEYPAD_I2C_ADDRESS   (0x42)

void main (void)
{
   /* Configure Pins */
   PINSEL_CFG_Type PinCfg;

   PinCfg.Funcnum     = PINSEL_FUNC_3;
   PinCfg.OpenDrain   = PINSEL_PINMODE_NORMAL;
   PinCfg.Pinmode     = PINSEL_PINMODE_PULLUP;
   PinCfg.Portnum     = I2C_SCL_SDA_PORT;

   PinCfg.Pinnum      = I2C_SDA_PIN;
   PINSEL_ConfigPin(&PinCfg);

   PinCfg.Pinnum      = I2C_SCL_PIN;
   PINSEL_ConfigPin(&PinCfg);

   // Configure I2C to run at 100000Hz
   I2C_Init(I2CDEV, 100000);
   
   // Enable the I2C device
   I2C_Cmd(I2CDEV, ENABLE);

   uint8_t data_out = 0x0F;
   uint8_t data_in = 0x00;

   I2C_M_SETUP_Type i2c_m_setup;

   i2c_m_setup.sl_addr7bit = KEYPAD_I2C_ADDRESS >> 1;
   i2c_m_setup.tx_data = &data_out;
   i2c_m_setup.tx_length = sizeof(data_out);
   i2c_m_setup.rx_data = &data_in;
   i2c_m_setup.rx_length = sizeof(data_in);
   i2c_m_setup.retransmissions_max = 3;

   Status i2c_status = I2C_MasterTransferData(I2CDEV, &i2c_m_setup, I2C_TRANSFER_POLLING);
   
   uint8_t keypad_row = data_in ^ 0xFF;
}
ADC (Analogue to Digital Converter)
Uses:
  • Reading real analogue signals with up to 12 bits of precision (0 - 4095) up to 200,000 times a second.
Notes:
  • On the University of York HostBoard the I2C interrupt line is connected to mbed pin 15. This means that if you wish to use ADC channel 0 (AD0.0) you cannot use I2C interrupt line for interrupts caused by the IO Expanders and the I2C Int jumper (under the keypad) must be removed to stop interrupt signals messing with the input you are trying to read.
  • The ADC seems to create quite a lot of noise in the form of very narrow tall spikes, this problem can be fixed by passing the read data through a low pass filter algorithm before using it if you do not mind the loss in accuracy as you get close to the cutoff frequency.
  • Noise from the ADC can be reduced by placing a 330pF capacitor between ground and the pin you are reading from.
  • On the University of York HostBoard mbed pin 19 is connected to the "audio in" 3.5mm stereo jack.
Pin Functions
AD0.x Analogue to Digital input/channel x
Code
Important headers:
Device struct defines:
  • LPC_ADC - The ADC device.
Interrupt defines:
  • ADC_IRQn - A to D conversion complete interrupt.
Example code: #include "LPC17xx.h"
#include "lpc_types.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_adc.h"

void main (void)
{
   // Set up the pin configuration struct for using analogue in on mbed pin 16.
   PINSEL_CFG_Type PinCfg;
   PinCfg.Funcnum   = PINSEL_FUNC_1;
   PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL;
   PinCfg.Pinmode   = PINSEL_PINMODE_PULLUP;
   PinCfg.Portnum   = PINSEL_PORT_0;
   PinCfg.Pinnum    = PINSEL_PIN_24;
   
   // Configure mbed pin 16 to use the analogue in channel 1 function (AD0.1).
   PINSEL_ConfigPin(&PinCfg);
   
   // Set up the ADC sampling at 200kHz (maximum rate).
   ADC_Init(LPC_ADC, 200000);
   
   // Enable ADC channel 1.
   ADC_ChannelCmd(LPC_ADC, ADC_CHANNEL_1, ENABLE);
   
   // Set ADC to continuously sample.
   ADC_StartCmd (LPC_ADC, ADC_START_CONTINUOUS);
   
   // Set ADC to start converting.
   ADC_BurstCmd (LPC_ADC, ENABLE);
   
   // Enable interrupts for ADC conversion completing.
   NVIC_EnableIRQ(ADC_IRQn);
   
   // Enable interrupts globally.
   __enable_irq();
}

// The ADC interrupt handler, gets called every time an A to D conversion completes.
void ADC_IRQHandler (void)
{
   // Get the value read on ADC channel 1.
   uint16_t analogue_value = ADC_ChannelGetData(LPC_ADC, ADC_CHANNEL_1);
   
   /* Now do something with the read analogue value. */
}
DAC (Digital to Analogue Converter)
Uses:
  • Creation of real analogue signals with 10 bits of precision (0 - 1023) that can change up to 1,000,000 times a second (with the 700mA bias).
Notes:
  • Remember that while the ADC is 12 bit the DAC is only 10 bit so if outputting a value read from the ADC onto the DAC the value must be right shifted 2 bits first (if you do not do this the DAC's register will overflow and you will see bits of your output cut into slices and shown next to each other seperated by rapid transitions from max to min or min to max).
Pin Functions
AOUT Analogue OUTput
Code
Important headers:
Device struct defines:
  • LPC_DAC - The DAC device.
Useful functions:
  • Initialise the DAC so it is ready for use:
            void DAC_Init (LPC_DAC_TypeDef* DACx)
  • Update the DAC output value to the 10 bit dac_value:
            void DAC_UpdateValue (LPC_DAC_TypeDef* DACx, uint32_t dac_value)
See: Public DAC functions.
Example code: #include "LPC17xx.h"
#include "lpc_types.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_dac.h"

void main (void)
{
   // Set up the pin configuration struct for using analogue out on mbed pin 18.
   PINSEL_CFG_Type PinCfg;
   PinCfg.Funcnum   = PINSEL_FUNC_2;
   PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL;
   PinCfg.Pinmode   = PINSEL_PINMODE_PULLUP;
   PinCfg.Portnum   = PINSEL_PORT_0;
   PinCfg.Pinnum    = PINSEL_PIN_26;
   
   // Configure mbed pin 18 to use the analogue out function.
   PINSEL_ConfigPin(&PinCfg);
   
   // Initialise the DAC so it is ready to use.
   DAC_Init(LPC_DAC);
   
   // Set DAC output to half (approx. 1.65v).
   DAC_UpdateValue (512);
   
   /* wait for at least
    * 1 us then do
    * more updates */

}
UART (Universal Asynchronous Receiver/Transmitter)
Uses:
  • ???
Notes:
  • UART device 0 can be used to write text to a terminal on a computer over the USB cable.
Pin Functions
TXDx Serial Output for UART device x
RXDx Serial Input for UART device x
Code
Important headers:
Device struct defines:
  • LPC_UART0 - UART device 0.
  • LPC_UART1 - UART device 1.
  • LPC_UART2 - UART device 2.
  • LPC_UART3 - UART device 3.
Interrupt defines:
  • UART0_IRQn - UART0 interrupt.
  • UART1_IRQn - UART1 interrupt.
  • UART2_IRQn - UART2 interrupt.
  • UART3_IRQn - UART3 interrupt.
PWM (Pulse Width Modulation)
Uses:
  • Creating pseudo-analogue signals (can use low pass filters to make a more true analogue signal).
  • Controlling servos.
Pin Functions
PWM1.x Pulse Width Modulation output x
Code
Important headers:
Device struct defines:
  • LPC_PWM1 - The PWM device.
Interrupt defines:
  • PWM1_IRQn - The PWM interrupt.
CAN (Controller Area Network)
Uses:
  • Direct microcontroller to microcontroller communication.
Notes:
  • On the University of York host board remeber to set the standby pin (pin 10 port 0) low to turn the CAN transceiver on.
Pin Functions
RDx Receive Data? x
TDx Transmit Data? x
Code
Important headers:
Device struct defines:
  • LPC_CAN2 - CAN device 2 (Used on University of York host board).
Interrupt defines:
  • CAN_IRQn - The PWM interrupt.

Using LPC17xx interrupts
  1. Look at the lpc17xx user guide to find which interrupt you need to use and when it is called (the start of the NVIC chapter is very helpful).
  2. Find the definition of the interrupt you want in LPC17xx.h (look in the IRQn/IRQn_Type enum at the top) or find it on this page e.g. ADC_IRQn for ADC interrupts.
  3. Include LPC17xx.h in the files where you want to use interrupts.
  4. Enable the interrupt you want to use with the void NVIC_EnableIRQ(IRQn_Type IRQn); function e.g. to enable ADC interrupts you would write: NVIC_EnableIRQ(ADC_IRQn);
  5. Make sure interrupts are globally enabled by calling __enable_irq();.
  6. Write the interrupt handler function, all interrupt handlers must have the signature void IRQName_IRQHandler(void); An easy way to find the correct name of the interrupt handler function is to get the name of the interrupt, remove the "n" from the end and replace it with "Handler" e.g. ADC_IRQn → ADC_IRQ → ADC_IRQHandler → void ADC_IRQHandler(void);
  7. If you have a critical section where interrupts must not occur call __disable_irq(); then call __enable_irq(); when it is safe for interrupts to occur again.
  8. When you do not want to use the interrupt any more use void NVIC_DisableIRQ(IRQn_Type IRQn); to disable the interrupt again.