LPC1114 Code Base Documentation
An overview of the main functions and structure of the LPC1114 Code Base
The LPC1114 Code Base should be relatively easy to understand on its own, but we've put together a basic summary and some examples of the main methods that you can use to interact with the LPC1114 Reference Board. While this documentation isn't exhaustive, it should serve as a good starting point.
Last updated 9 June 2010. The software itself is still in development, and this documentation is provided to give an indication of the current state of development, though it may not be entirely up to date, and should not be considered final until an official release is made.
The LPC1114 Code Base has a fairly simple project structure, with all peripheral and device-specific code placed in the "core/" folder, any drivers for external HW in the "drivers/" folder, and core application files placed in the root directory (notably projectconfig.h and the system header file lpc111x.h).
Project Files
Project files for CodeLite (a free cross-platform, open-source IDE) and Rowley Associates Crossworks for ARM (commercial) are included in the "build/.." folder. While both of these IDEs use the same underlying peripheral code, they do not compile using the same toolchain. CodeLite runs the Makefile in the root folder and requires a GNU GCC toolchain for ARM to be installed on your computer. Crossworks for ARM uses it's own GCC toolchain and startup code, and does not use the Makefile included in the root folder. Crossworks is ideal for complex projects where HW debugging is required (using a HW debugger like the Segger J-Link), but CodeLite should allow you to get started without a significant investment in HW and SW.
If you do not wish to use an IDE, you can also build directly from the command-line using the included Makefile in the root folder and an appropriate GNU GCC toolchain for ARM. (If you're feeling particularly adventurous, you can also have a look at our tutorial on building a GCC toolchain from source.)
lpc111x.h
In order to make understanding (and debugging) any projects based on the LPC1114 Code Base as easy as possible, a new system header file was created. While several header files already exist for the LPC1114, we really wanted to eliminate the use of "magic-numbers" throughout the code, so we decided to cozy up with the user manual and make our own header file. Along with the normal system registers, lpc111x.h contains appropriately labelled definitions for almost all the individual bits that can be set for each register. While there is obviously a fair amount of work involved in putting all this information into the header file, the end result is code that is much easier to understand, particularly if you are inheriting a project initially managed or created by someone else.
What are Magic Numbers?
Entering raw ("magic") numbers into your program may be quicker on the front-end of a project, but which of these two (identical when compiled) lines of code would you rather be faced with debugging six months from now?
UART_U0LCR = 0x83;
UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
UART_U0LCR_Stop_Bit_Select_1Bits |
UART_U0LCR_Parity_Disabled |
UART_U0LCR_Break_Control_Disabled |
UART_U0LCR_Divisor_Latch_Access_Enabled); projectconfig.h
The projectconfig.h file contains a variety of definitions and enumerations that are used throughout the project. By placing this information in one file, it's much easier to maintain up-to-date code when small changes are made, such as adjusting the speed of the system clock, as well as allowing one central location to enable or disable various code blocks or device features.
Core Peripherals (core/...)
Code to initialise and interact with all of the internal peripherals on the LPC1114 is located in the 'core' folder.
External Hardware (drivers/...)
Any code that interacts with external HW is located in the 'drivers' folder.
Most of the peripherals available on the LPC1114 or accessible using the code provided in the LPC1114 Code Base, including methods to initialise and interact with them. For details on customising the behaviour of individual peripherals, consult the latest version of the LPC1114 User Manual.
The LPC1114 can be configured to run at speeds up to 59MHz. By default, the core system clock will be set to 12MHz, using the external 12MHz crystal. (The LPC1114 also contains an internal 12MHz oscillator, but it isn't as accurate as an external crystal.) In order to reduce power consumption all pins are set to GPIO and input, with their internal pull-up resistors left in the default "pull-up" state (meaning all pins are being pulled high after the cpu is first initialised). If you wish to use a lower speed system clock (which will consume less power), or configure the default pin states differently, you will need to modify the code in the cpuInit method.
Initialises the system clocks to use the external crystal and run at 12MHz (12MHz x 1 = 12MHz). This should be the first function called by your application, since the rest of the LPC1114 Code Base will not perform as expected if the CPU is in an 'unknown' state. All pins are set to GPIO with the internal pull-up resistor enabled (to reduce power consumption by ensuring that no pins are left 'floating').
Arguments #include "core/cpu/cpu.h"
int main(void)
{
cpuInit();
// Enter permanent loop
while(1);
}
Get's the CPU part number from the CPU ID register
Arguments Returns cpuDeviceID_LPC1111, cpuDeviceID_LPC1112, cpuDeviceID_LPC1113, cpuDeviceID_LPC1114 or cpuDeviceID_Unknown
#include "core/cpu/cpu.h"
int main(void)
{
cpuInit();
cpuDeviceID_t id = cpuGetDeviceID();
if (id == cpuDeviceID_LPC11114)
{
// Part is either LPC1114FBD48 or LPC1114FHN33
}
// Enter permanent loop
while(1);
}
The LPC1114 includes an 8-channel, 10-bit analog-to-digital converter (ADC), capable of measuring between 0 and 3.6V (not to exceed VDD, which is set to 3.3V in the case of the LPC1114 Reference Board). Each channel can be read individually, or all eight channels can be read at once in 'Burst' mode. Currently, only one channel is read at a time for simplicity sake (this should be sufficient for most situations).
Initialises the A/D converter and configures channels 0..3 for 10-bit, SW-controlled A/D conversion.
Arguments This function will manually start an A/D conversion on a single channel (0..7) and return the conversion results (0..1023).
Arguments - uint8_t channelNum: The A/D channel [0..7] that will be used during the A/D conversion.
Returns 0 if an overrun error occurred, otherwise a 10-bit value containing the A/D conversion results.
Warning Only AD channels 0..3 are configured for A/D in adcInit. If you wish to use A/D pins 4..7 they will also need to be added to the adcInit function
#include "core/cpu/cpu.h"
#include "core/adc/adc.h"
void main (void)
{
cpuInit();
adcInit();
uint32_t results = 0;
while(1)
{
// Get A/D conversion results from A/D channel 0
results = adcRead(0);
}
}
GPIO (General Purpose Input/Output) is used for digital I/O, and each pin can be configured as either an input (meaning that you can read the pin's externally adjustable state) or as an output (to turn an LED on or off, for example). In addition to simple I/O, every GPIO pin on the LPC1114 can be configured to behave as an external interrupt source, meaning that an interrupt can be raised when a pin's state changes (such as a button being pressed). This is different than some earlier ARM7 chips that had a limited number of EINTs. Each GPIO pin also has an internal resistor that can either be disabled or configured to work in pull-up, pull-down, or 'repeater' mode (see the User Manual for further details on the different modes). While the addition of internal resistors is, in itself, a welcome addition since it reduces the overall external parts count and adds more flexibility to your system, it also requires a bit more attention on the part of developpers to make sure that the resistor is always set in an appropriate state (see gpioSetPullup for further details).
Initialises GPIO and enables the GPIO interrupt handler for all GPIO ports.
Arguments Sets the direction (input/output) for a specific port pin.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
- dir: the pin direction (gpioDirection_Input or gpioDirection_Output)
Sets the value for a specific port pin (only relevant when a pin is configured as output).
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
- bitVal: indicates whether the pin should be set high (1) or low (0).
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to output
gpioSetDir(1, 8, gpioDirection_Output);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
// Set GPIO1.8 high
gpioSetValue(1, 8, 1);
while(1);
} Gets the value for a specific port pin.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
Returns 1 if the pin is currently high, or 0 is the pin is currently low.
Warning All GPIO pins on the LPC1114 have internal pull-up/pull-down resistors that can be individually configured. By default, the LPC1114 will enable the pull-up resistors on most pins when it comes out of reset. The rationale behind this decision is that placing the pins in a defined state will avoid wasting power when pins are left 'floating', but it can also cause some confusion if you are not explicitly setting the resistors to a different state yourself should this be required. In order to avoid problems, you should always explicitly set the state of the internal resistor using gpioSetPullup.
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to input
gpioSetDir(1, 8, gpioDirection_Input);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
uint32_t results = 0;
while(1)
{
// Read the current state of GPIO1.8 (1 = high, 0 = low)
results = gpioGetValue(1, 8);
}
} All GPIO pins on the LPC1114 have internal pull-up/pull-down resistors that can be individually configured. This method can be used to explicitly set the internal resistor's 'mode' of operation. For details on the different modes (inactive, pull-up, pull-down, or repeater) see the LPC1114 User Manual.
Arguments - *ioconReg: pointer to the IOCON register for the appropriate pin (ex. 'IOCON_PIO1_8' for GPIO 1.8, 'IOCON_PIO2_2' for GPIO 2.2, etc.). Note: Since this is a pointer, you need to pass the 'address' of the register in to the method, and not it's value. This can be accomplished by placing a '&' just before the name of the IOCON register, for example: 'gpioSetPullup(&IOCON_PIO2_2, gpioPullupMode_Inactive);'.
- mode: the mode to set the internal resistor to (gpioPullupMode_Inactive, gpioPullupMode_PullDown, gpioPullupMode_PullUp or gpioPullupMode_Repeater).
Warning By default, the LPC1114 will enable the pull-up resistors on most pins when it comes out of reset. The rationale behind this decision is that placing the pins in a defined state will avoid wasting power when pins are left 'floating', but it can also cause some confusion if you are not explicitly setting the resistors to a different state yourself should this be required. In order to avoid problems, you should always explicitly set the state of the internal resistor.
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8, 1.9, 1.10 and 1.11 to input
gpioSetDir(1, 8, gpioDirection_Input);
gpioSetDir(1, 9, gpioDirection_Input);
gpioSetDir(1, 10, gpioDirection_Input);
gpioSetDir(1, 11, gpioDirection_Input);
// Enable the pull-down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_PullDown);
// Enable the pull-up resistor on P1.9
gpioSetPullup (&IOCON_PIO1_9, gpioPullupMode_PullUp);
// Disable the internal resistor resistor on P1.10
gpioSetPullup (&IOCON_PIO1_10, gpioPullupMode_Inactive);
// Set P1.11 to 'Repeater' (remembers the last state explicitly set)
gpioSetPullup (&IOCON_PIO1_11, gpioPullupMode_Repeater);
while(1);
} Any GPIO pin on the LPC1114 can be configured as an external interrupt source. The gpioSetInterrupt method allows you to determine which pins act as an interrupt source, and specify the conditions under which an interrupt should be raised (if the pin goes high or low, etc.). Depending on the portNum specified, the interrupt will be handled (by default) by PIOINTx_IRQHandler, where 'x' is the port number in question (PIOINT1_IRQHandler would be entered if an interrupt was raised on GPIO pin 1.8, for example).
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
- sense: whether the interrupt should be configured as edge (gpioInterruptSense_Edge) or level (gpioInterruptSense_Level) sensitive.
- edge: whether an interrupt is triggered on one edge (gpioInterruptEdge_Single) or on both (gpioInterruptEdge_Double).
- event: whether the rising edge (gpioInterruptEvent_ActiveHigh) or the falling edge (gpioInterruptEvent_ActiveLow) should be used to trigger the interrupt. ActiveHigh means that a HIGH level on the pin will trigger an interrupt, ActiveLow means that a LOW level on the pin will trigger an interrupt.
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to input
gpioSetDir(1, 8, gpioDirection_Input);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
// Setup an interrupt on GPIO1.8
gpioSetInterrupt(1, // Port
8, // Pin
gpioInterruptSense_Edge, // Edge Sensitive
gpioInterruptEdge_Single, // Single Edge
gpioInterruptEvent_ActiveHigh); // Active High
// Enable the interrupt
gpioIntEnable(1, 8);
while (1);
}
Enables an interrupt on the specified GPIO pin.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
Disables an interrupt on the specified pin.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
Clears the interrupt on the specified pin. This method should only be called from withint the interrupt service routine (ISR) once the interrupt has been raise.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
// IRQ Handler for GPIO Port 1
void PIOINT1_IRQHandler(void)
{
uint32_t regVal;
// Check if pin 1.8 raised the interrupt
regVal = gpioIntStatus(1, 8);
if (regVal)
{
// Do Something
...
// Clear the interrupt
gpioIntClear(1, 8);
}
return;
} Gets the interrupt status for a specific port pin.
Arguments - portNum: the gpio port number [0..3]
- bitPos: the bit position for the gpio pin [0..11]
Returns '1' if an interrupt was raised by the specified pin, otherwise '0'.
Configures the Power Management Unit (PMU) to control sleep, deep-sleep and power-down modes. GPIO 0.0..11 and 1.0 can be configured to wake the device up from sleep modes, but only a low-level on pin 1.4 (WAKEUP) can wake the device up from power-down.
Initialises the power management unit, and configures pin 0.1 to act as a wakeup source from sleep or deep-sleep mode.
Arguments Notes For sleep and deep-sleep modes -- entered via pmuSleep and pmuDeepSleep-- any I/O pin can be used as a wakeup source. For deep power-down mode -- entered via pmuPowerDown -- only a low level on pin 1.4 (WAKEUP) can wake the device up.
By default, only P0.1 is configured as a wakeup source, but the appropriate code to enable any other pin as a wakeup source (from sleep or deep-sleep mode) is provided in pmuSleep and simply needs to be uncommented (the pin configured for GPIO may also need to be set to GPIO, following the example for P0.1).
This function will put the device into sleep mode. Gpio pins 0.0..11 and 1.0 can be used to wake the device up (however, the pins must first be configured for this in pmuInit).
Arguments #include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
// Configure wakeup sources before going into sleep/deep-sleep.
// By default, pin 0.1 is configured as wakeup source (falling edge)
pmuInit();
// Enter sleep mode
pmuSleep();
while(1)
{
// Wait for an interrupt to wake the device up
}
} This function will put the device into deep-sleep mode. Any gpio pin can be used to wake the device up (however, the pins must first be configured for this in pmuInit). The sleepCtrl parameter is used to indicate which peripherals should be put in sleep mode (see the SCB_PDSLEEPCFG register for details). Optionally, providing a non-zero value to wakeupSeconds will cause the device to wakeup from deep-sleep after the specified delay using 32-bit timer 0 and pin 0.1 (CT32B0_MAT2).
Arguments
- sleepCtrl: The bits to set in the SCB_PDSLEEPCFG register. This controls which peripherals will be put in sleep mode.
- wakeupSeconds: If this is greater than 0, the device will be configure to wakeup from deep-sleep after the specified number of seconds.
#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
uint32_t pmuRegVal;
// Configure wakeup sources before going into sleep/deep-sleep.
// By default, pin 0.1 is configured as wakeup source (falling edge)
pmuInit();
// Inidicate which peripherals should be disabled in deep-sleep
pmuRegVal = SCB_PDSLEEPCFG_IRCOUT_PD |
SCB_PDSLEEPCFG_IRC_PD |
SCB_PDSLEEPCFG_FLASH_PD |
SCB_PDSLEEPCFG_USBPLL_PD |
SCB_PDSLEEPCFG_SYSPLL_PD |
SCB_PDSLEEPCFG_SYSOSC_PD |
SCB_PDSLEEPCFG_ADC_PD |
SCB_PDSLEEPCFG_BOD_PD;
// Enter deep sleep mode and wakeup after 10 seconds
pmuDeepSleep(pmuRegVal, 10);
while(1)
{
}
} This function will configure the PMU control register and enter deep power-down mode. Optionally, pre-determined values can be stored in the four general-purpose registers (PMU_GPREG0..3), which can be used to persist any essential system settings while the device is in deep power-down mode, so long as 3.3V is still available.
Arguments Warning The only way to wake a device up from deep power-down mode is to set a low-level on P1.4 (WAKEUP). If 3.3V power is lost, the values stored in the four general-purpose registers will also be lost.
#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
pmuInit();
// Enter power-down mode
pmuPowerDown();
while(1)
{
// Device was woken up by WAKEUP pin
}
}
Generic code for SSP/SPI communications. By default, the SSP block is initialised in SPI master mode
Initialises the SSP port. By default, SSP is set to SPI frame-format with 8-bit data. Pin 2.11 is routed to serve as serial clock (SCK), and SSEL (0.2) is set to GPIO to allow manual control of when the SPI port is enabled or disabled. Overrun and timeout interrupts are both enabled.
Arguments - portNum: The port number.
- polarity: Indicates whether the clock should be held high (sspClockPolarity_High) or low (sspClockPolarity_Low) when inactive.
- phase: Indicates whether new bits start on the leading (sspClockPhase_RisingEdge) or falling (sspClockPhase_FallingEdge) edge of clock transitions
Notes sspSelect() and sspDeselect() macros have been defined in ssp.h to control the SSEL line without having to know the specific pin being used.
Sends a block of data to the SSP port
Arguments - portNum: The port number.
- *buf: Pointer to the data buffer
- length: Block length of the data buffer
#include "core/cpu/cpu.h"
#include "core/ssp/ssp.h"
#define SSP_FIFOSIZE 8
int main(void)
{
cpuInit();
sspInit(0, sspClockPolarity_High, sspClockPhase_RisingEdge);
uint8_t request[SSP_FIFOSIZE];
uint8_t response[SSP_FIFOSIZE];
// Send 0x9C to the slave device and wait for a response
// Fill request buffer
request[0] = 0x80 | 0x1C;
// Enable CS line
ssp0Select();
// Send the 'request' data (1 byte)
sspSend(0, (uint8_t *)&request, 1);
// Wait for the response (1 byte)
sspReceive(0, (uint8_t *)&response, 1);
// Disable CS line
ssp0Deselect();
} Receives a block of data from the SSP port
Arguments - portNum: The port number.
- *buf: Pointer to the data buffer
- length: Block length of the data buffer
Core/Systick
Controls the 24-bit 'system tick' timer, which can be used as a generic timer or to control time sharing with an embedded real-time operating system (FreeRTOS, Crossworks CTL, etc.).
Initialises the systick timer with the specified delay in millaseconds (typical 10ms). This will cause a systick interrupt to be raised every x millaseconds, and an unsigned 32-bit variable named "msTicks" will be incremented by one every time the interrupt is fired.
Arguments - delayMs: Indicates the length of time in millaseconds between each system 'tick'.
Causes a blocking delay for the specific number of systick timer ticks. The length of the delay depends on the value supplied to the systickInit function. The delay can be calculated by multiplying delayMs from systickInit with delayTicks. (For example, if the systick timer is configure for 10mS ticks, a delayTicks value of 15 would cause a 150mS delay.)
Arguments - delayTicks: The number of systick ticks to wait.
#include "core/cpu/cpu.h"
#include "core/systick/systick.h"
int main (void)
{
// Initialise the cpu
cpuInit();
// Initialise the systick timer with one tick every 10 millaseconds
systickInit(10);
while(1)
{
// Wait 15 ticks on the systick timer (meaning 150ms)
systickDelay(15);
// Do something ...
}
}
Controls either of the 16-bit timers available on the LPC1114. It's worth noting that while the 16-bit and 32-bit timers are functionally identical, the 16-bit timers are limited to roughly 5.46mS (or 5461uS) on a system running at 12MHz, or 1.37mS running at 48MHz since:
1 mS = CFG_CPU_CCLK / 1000
= 12000000 / 1000
= 12000 'ticks'
Thus the maximum value of a 16-bit timer, 0xFFFF (65535), is equal to 5.46125 milliseconds. As such, if you are using the timers exclusively for timing delays, you may want to consider using a 32-bit timer since it provide a much larger maximum delay. The 16-bit timers are still very useful for a number of other situations, or if you required very fine-grained control over timing, but are limited to millisecond and microsecond timing. (Running the system at a slower clock speed will also increase the maximum delay possible with a 16-bit timer.)
Both 16-bit and 32-bit timers can be used in co-ordination with external pins so that when a 'match' occurs (after a predetermined delay), a pin can either be set high, low, or toggled. Each timer's match register can also be configured as PWM, allowing you to create single edge controlled PWM outputs.
Blocking versus non-blocking delays: Two different types of delays are supported with this code (though the timers can be used for more than just delays!). The first type of delay, using
timer16DelayTicks and
timer16DelayUS, is referred to as a
blocking delay since it will block the execution of any other code (except an interrupt) until the specified delay has passed. This can be both desirable or undesirable, depending on the task as hand. The second type of delay is based on interrupts, and involves simply checking a pre-defined variable that will increment by one every time a fixed delay elapses. (The 32-bit variable that counts up will automatically 'roll-over' to 0 once 0xFFFFFFFF has been reached.) An example of how to use this
non-blocking delay is visible in the example for
timer16Init.
Initialises a 16-bit timer with the supplied timer interval (the amount of time that passes between each timer 'tick'). Every time that this interval elapses, the timer's interrupt will be fired and the appropriate counter variable will be incremented by one (For example, with CT16B0, 'timer16_0_counter' would be incremented).
Arguments - timerNum: The 16-bit timer to initialise [0..1]
- timerInterval: The number of clock 'ticks' between resets [0..65534]
Warning Care needs to be taken when configuring the timers since the pins are all multiplexed with other peripherals. This code is provided as a starting point, but it will need to be adjusted according to your own situation and pin/peripheral requirements
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
// Instantiated in timer16.c
extern volatile uint32_t timer16_0_counter;
int main(void)
{
cpuInit();
// Initialise timer0 with a delay of 0xFFFF, which will cause the
// timer interrupt to fire every 65535 ticks and increment
// timer16_0_counter by 1
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
// At this point timer16_0_counter should start incrementing by 1
// every 65535 ticks
while(1)
{
// If the timer has been fired 10 times, disabled the timer
if (timer16_0_counter == 10)
{
timer16Disable(0);
}
}
} Causes a blocking delay for the specified number of clock ticks.
Arguments - timerNum: The 16-bit timer to use [0..1]
- delayInTicks: The number of clock ticks to delay [0..65534]
Notes The exact duration of this delay depends on the speed of the system clock, but it will invariably be short because of the 16-bit limitation. For example, on a system with a 48MHz clock, a 1mS delay would be equal to 48,000 ticks, which is very close to the maximum 16-bit value of 65,535. Thus, the maximum delay measured in mS with a 48MHz clock is ~1.37mS.
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
int main(void)
{
cpuInit();
// Initialise timer 0 ... delay is provided but not used here
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
while(1)
{
// Cause blocking delay for 6000 ticks (0.5mS @ 12MHz)
// Note: The delay must be 65535 or less (16-bit value)
timer16DelayTicks(0, 6000);
}
} Causes a blocking delay for the specified number of microseconds.
Arguments - timerNum: The 16-bit timer to use [0..1]
- delayInUS: The number of microseconds to wait
Warning The maximum delay in uS will depend on the clock speed, but running at 12MHz the maximum delay (MR = 0xFFFF) would be 5461uS (0xFFFF / 12 = 5461.25), or 5.46 milliseconds.
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
int main(void)
{
cpuInit();
// Initialise timer 0 ... delay is provided but not used here
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
while(1)
{
// Cause blocking delay for 500 microseconds (0.5mS)
timer16DelayUS(0, 500);
}
} Enables the specified timer (which will cause any configured interrupts to fire)
Arguments - timerNum: The 16-bit timer to enable [0..1]
Disables the specified timer (which will stop any configured interrupts from firing)
Arguments - timerNum: The 16-bit timer to disable [0..1]
Resets the specified timer.
Arguments - timerNum: The 16-bit timer to reset [0..1]
Controls either of the 32-bit timers available on the LPC1114. It's worth noting that while the 16-bit and 32-bit timers are functionally identical, but the 32-bit timers support a much longer delay. For example, on a system running at 48MHz:
1 mS = CFG_CPU_CCLK / 1000
= 48000000 / 1000
= 48000 'ticks'
Thus the maximum value of a 32-bit timer, 0xFFFFFFFF (4,294,967,295), is equal to 89478 milliseconds (slightly less than 1.5 minutes). As such, if you are using the timers exclusively for timing delays, you may want to consider sticking to 32-bit timers since they provide a much larger maximum delay (versus ~1.37 milliseconds with a 16bit timer @ 48MHz).
Both 16-bit and 32-bit timers can be used in co-ordination with external pins so that when a 'match' occurs (after a predetermined delay), a pin can either be set high, low, or toggled. Each timer's match register can also be configured as PWM, allowing you to create single edge controlled PWM outputs.
Initialises a 32-bit timer with the supplied timer interval (the amount of time that passes between each timer 'tick'). Every time that this interval elapses, the timer's interrupt will be fired and the appropriate counter variable will be incremented by one (For example, with CT32B0, 'timer32_0_counter' would be incremented).
Arguments - timerNum: The 32-bit timer to initialise [0..1]
- timerInterval: The number of clock 'ticks' between resets [0..4,294,967,295]
Warning Care needs to be taken when configuring the timers since the pins are all multiplexed with other peripherals. This code is provided as a starting point, but it will need to be adjusted according to your own situation and pin/peripheral requirements
#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"
// Instantiated in timer32.h
extern volatile uint32_t timer32_0_counter;
int main(void)
{
cpuInit();
// Initialise timer0 with a delay of 12000, which will cause the
// timer interrupt to fire every 1mS @ 12MHz and increment
// timer32_0_counter by 1
timer32Init(0, 12000);
// Enable the timer
timer32Enable(0);
// At this point timer32_0_counter should start incrementing by 1
// every 12000 ticks
while(1)
{
// If the timer has been fired 10 times, disabled the timer
if (timer32_0_counter == 10)
{
timer32Disable(0);
}
}
} Causes a blocking delay for the specified number of 'ticks' on the timer. The duration of each tick is determined by the 'timerInterval' property supplied to timer32Init
Arguments - timerNum: The 32-bit timer to use [0..1]
- delay: The number of timer counter increments to wait
Warning The maximum delay will depend on the the 'timerInterval' value supplied when initialising the timer (see timer32Init).
#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"
int main(void)
{
cpuInit();
// Initialise timer 0 with 1 millisecond 'ticks'
timer32Init(0, TIMER32_CCLK_1MS);
// Enable the timer
timer32Enable(0);
while(1)
{
// Cause a blocking delay for 1.5 seconds (1500 milliseconds)
timer32Delay(0, TIMER32_DELAY_1MS * 1500);
}
} Enables the specified timer (which will cause any configured interrupts to fire)
Arguments - timerNum: The 32-bit timer to enable [0..1]
Disables the specified timer (which will stop any configured interrupts from firing)
Arguments - timerNum: The 32-bit timer to disable [0..1]
Resets the specified timer.
Arguments - timerNum: The 32-bit timer to reset [0..1]
Allows simple text messages to be sent and received over a serial port or USB to serial-port bridge like the FTDI232RL. Any incoming text is placed in a FIFO queue to all the data to be safely processed, without having to worry about new data arriving via the interrupt during processing.
Get a pointer to the UART's protocol control block, which can be used to check the UART status value, determine whether UART has already been initialised or not, determine if any outgoing data is waiting to be transmitted, and get a reference to the RX FIFO.
Arguments // Make sure that UART is initialised
uart_pcb_t *pcb = uartGetPCB();
if (!pcb->initialised)
{
uartInit(CFG_UART_BAUDRATE);
}
Initialises UART at the specified baud rate.
Arguments - baudRate: The baud rate to use when configuring the UART (ex. '57600').
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"
#define UARTBUFFERSIZE 5
int main(void)
{
cpuInit();
uartInit(57600);
uint8_t uartBuffer[UARTBUFFERSIZE] = { 'T', 'e', 's', 't', '\n' };
while(1)
{
// Constantly send contents of uartBuffer
uartSend((uint8_t *)uartBuffer, UARTBUFFERSIZE);
}
} Sends the contents of the buffer over UART.
Arguments - *bufferPtr: Pointer to the text buffer
- length: The size of the text buffer
Sends a single byte over UART.
Arguments // Send 0xFF over UART
uartSendByte(0xFF);
// Send 'B' over UART (note single quotes)
uartSendByte('B'); Initialises the RX FIFO buffer.
Arguments No example current available.
Read one byte out of the RX buffer. This function will return the byte located at the array index of the read pointer, and then increment the read pointer index. If the read pointer exceeds the maximum buffer size, it will roll over to zero.
Arguments Write one byte into the RX buffer. This function will write one byte into the array index specified by the write pointer and increment the write index. If the write index exceeds the max buffer size, then it will roll over to zero.
Note: Normally you will not need to call this method yourself. All incoming data is handled by the UART ISR, and any bytes received via UART are automatically inserted in the RX buffer. You simply need to check for new messages at appropriate intervals by testing the return value of uartRxBufferDataPending() or looking at the value of "pcb->rxfifo.len" on the UART control block (which will be non-zero if data is present in the RX buffer).
Arguments - uint8_t data: The byte to add to the RX buffer.
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"
int main(void)
{
cpuInit();
uartInit(57600);
// Add 0xFF to the RX buffer
uartRxBufferWrite(0xFF);
// Check if the buffer is empty (it shouldn't be!)
while (uartRxBufferDataPending())
{
// Retrieve the first available character in the buffer
uint8_t c = uartRxBufferRead();
}
...
} Clears the FIFO read and write pointers and sets the length to zero.
Arguments No example currently available.
Determines whether there is any data in the FIFO queue. If one or more bytes are present in the FIFO, this method will return 1. If the buffer is empty, it will return 0.
Arguments
The LPC1114 includes a watchdog timer that can be used to detect when the system has stopped responding. The 'watchdog' is configured to be fed every 'x' ticks on the system clock, and if it isn't fed it will perform one of several actions selected by the user (such as resetting the system, or raising an interrupt). By default, the supplied code will setup the WDT to be fed at a rate of 250kHz (once every 250,000 ticks), and it will simply raise an interrupt (handled by WDT_IRQHandler) if it is not fed within the specified delay.
Initialises the watchdog timer and sets up the interrupt (reset is not enabled by default).
Arguments #include "core/cpu/cpu.h"
#include "core/wdt/wdt.h"
int main(void)
{
cpuInit();
wdtInit();
// Pat the watchdog to start it
wdtFeed();
while(1)
{
// Keep the watchdog happy by regularly feeding it
wdtFeed();
// Any delay here > 250,000 ticks (~3.5mS @ 72MHz)
// will cause the watchdog to raise an interrupt, which
// will be handled by WDT_IRQHandler
}
}
Feeds the watchdog to keep it from timing out.
Arguments