Many engineers use 8 bit microcontrollers because of their low cost and ease of use. 32 bit microcontrollers generally offer higher performance than 8 bit parts, but many believe their cost is significantly higher than bit uCs and that they are more difficult to use than 8 bit parts. While 32 bit parts are generally a little more complicated than 8 bit parts, the cost of 8 and 32 bit parts aren’t that far apart in many cases. Additionally, the 32 bit parts offer significantly higher performance. In other words, give 32 bit parts a chance!
NXP has introduced a very low cost (i.e. often less than $1 in production volumes) line of 32 bit microcontrollers, the LPC111X family. There are several other companies also offering some type of ARM Cortex M0 microcontroller. NXP was one of the earliest, but Freescale (Kinetis L), ST Micro (STM32 F0), and Nuvoton (M051,M058,Mini51,NUC100,NUC122) also have Cortex M0 offerings. This document will give a brief introduction on how to get up and running using NXP's LPC1114. The code will work on several other members of the LPC11xx family as well.
The assumption inherent in this document is that most engineers follow a fairly similar method of learning when presented with a new microcontroller family. They start by getting a development kit and trying to toggle a pin, transmit/receive with a serial port, read an ADC pin etc. This document will show some very simple examples of how to enable and operate these peripherals. This will not be exhaustive of every operating mode and every peripheral but, it is hoped that it will cover the basics in sufficient detail to allow an engineer to get up and running quickly. Also included are some tips regarding custom design of PCBs using these parts (see example schematic and BOM below in the "Hardware" section.
This document is primarily targeted at those who are familiar with 8 bit microcontrollers, but are interested in learning to use a 32 bit part. It is hoped that this document can make getting started with a 32 bit part as painless as possible. It is realized that this code is very simplistic, and if one were going to write production code, there would certainly be other features, such as error checking, that would be needed. This code is provided purely to provide a simplistic “working” example.
The examples described in this document will be run on Embedded Artists’ EA-XPR-002 (shown at the top of this wiki page). It should be noted that EA-XPR-002 from Embedded Artists is identical to OM11049,598 from NXP. So the two part numbers can be used interchangeably. This document generally refers to EA-XPR-002, but that is just for convenience. Any example given in this document should work on both boards using the Code Red Software (discussed below). This PCB can be used standalone, plugged into a solderless breadboard, or it can be plugged into a dedicated base board such as EA-XPR-021 (shown in Figure 1 below). The EA-XPR-002 or the OM11049,598 plugs in on top of this baseboard and allows you to use the peripherals of the LPC1114 in an easily measurable/observable way. Since this page was first built NXP purchased Embedded Artists and has obsoleted the EA-XPR-002. So just use the OM11049,598. All the examples should work exactly the same.
Figure 1: NXP's EA-XPR-021
If the LPC1114 (or any other LPC111X device) is being designed into a custom board here are a couple examples of how to connect the part to the programming header (plus part numbers). This circuit was built and successfully tested with the parts indicated.
Digi-Key Part Number
534237-6 (TE Connectivity)
EMK107B7105KA-T (Taiyo Yuden)
Figure 2: Here here are some examples of basic circuits that can be used to get the LC1114 up and running on a custom board. It should be noted that the connector, J1, has the pins on the left and right side shorted together so 1 and 2 are shorted together as are 3 and 4 etc. The connector, 5535676-7, has the advantage of being very securely attached to the PCB. Other connector options are shown as well. A possible mating connector for the three connectors given/shown above is 961108-5604-AR from 3M
Above (figure 3) is a pictorial example of how the OM11049,598 can be used as an inexpensive programmer/debugger. The OM11049,598 board can be carefully split in two using a “Dremel” tool, at least that’s how separation was accomplished in this case. Wear safety glasses! Alternatively, I was told by an NXP applications engineer that some customers have found that an old style paper cutter (see Figure 4) works very well too. If you don't like the idea of cutting the board, the OM11049,598 can be used without physically splitting the PCB in two. To prepare for use without sawing it in half, use an “exacto” knife to cut the traces between the two rows of vias that compose J4. Then solder a vertical connector into the vias on the programmer/debugger side.
Figure 5: Here a split OM11049,598 is used as a programmer/debugger with a custom PCB. In this case, 961108-5604-AR is the connector on the programmer/debugger and PPTC081LGBN-RC is the mating connector on the custom PCB.
All software examples were written in the C programming language using LPCXpresso v4.1.5 [12/12/2011] development system. This development environment is available free of charge at http://www.support.code-red-tech.com/CodeRedWiki; The comments in the code examples that have a parenthetical note such as (sec 3.5.14) refer to the NXP's "UM10398 LPC11x/LPC11Cxx User Manual" Rev. 12 - 24 September 2012
Important Note: Many of the software examples below write to a register with a name that begins with "LPC_IOCON...". All of these code samples have been tested and run on real hardware. However on another custom circuit board the author found that in order to successfully modify these registers the following piece of code had to be included:
So if one of the code examples shown here doesn't function correctly. Check and see if one of the "LPC_IOCON..." registers are being modified. If so, add the line of code above before trying to write to an "LPC_IOCON..." register and see if that fixes the problem. The author found this to be the solution to a problem experienced when using pin PIO1_1 (pin 34 on the 48 pin QFP part). The pin wouldn't toggle until the line above was added enabling the clock to the IOCON register. So keep this in mind when using the examples here.
Code Example 0: Toggle a GPIO Pin
This code snippet shows a simple program that was compiled and run on the LPCXpresso board successfully. The program toggles pin 23 on and off within the infinite while loop. Pin 23 will turn the boards lone LED on and off. For more examples of this type click here or here (for a plain text file).
Important Note: The LPC1114 toggles pins rather slowly. If you set the oscillator to a frequency of 48MHz and comment out the two "for" loops you’ll find that this program will only toggle a pin at around 1MHz. It’s something to be aware of if you are planning to toggle pins in a timing critical application. Some other NXP chips such the LPC13xx, LPC17xx, LPC23xx, LPC8xx, and some members of the LPC21xx family have “fast GPIO” that will toggle much faster than the LPC111X parts.
Code Example 1: Read a GPIO Pin
This program reads pin 40 (PIO1_4/AD5) and toggles pin 23 in response to pin 40s state. If pin 40 is high, the pin 23 is set high and vice versa. Recall that on the OM11049,598 board pin 23 is attached to an LED. This LED turns on when pin 23 is high. For more examples of reading pins as general purpose inputs click here. Note that pin 40 is labelled as "AD5" on the OM11049,598 PCB since it serves dual function as an analog to digital converter input if configured differently.
In order to change the state of pin 40 on the OM11049,598 board a switch such as 450-1467-ND may be used in conjunction with the pull up (or pull down) functions of PIO1_4 itself. The default state of the pin is to be pulled up.
Code Example 2: Setting Up the Oscillator
Here is a bit of code that will set the clock generation unit to produce a 48MHz clock from the 12MHz system oscillator and connects this clock to the ARM Cortex-M0 core. This operation is discussed in the user’s manual primarily in Chapter 3, section 3.4. The block diagram shown in Figure 8 is particularly useful in understanding the function of the code.
The critical bit of code to keep in mind is this line:
This is where the frequency is actually set. If you look at section 3.5.3 you can see how this value is constructed. In this case, it is 0x23. A value of 0x23 means that MSEL has a binary value of 0_0011, and PSEL has a binary value of 01. Combined as shown in section 3.5.3 they give a binary value of 010_0011, or a hex value of 0x23. Table 46 in section 188.8.131.52 gives MSEL and PSEL values for two other frequencies as well: 0x42 for 36MHz and 0x41 for 24MHz.
If you want to look at the output of the clock directly and you aren’t using pin PIO0_7 (pin 23 on the LQFP48 package), you can port the internal clock directly to the outside world on this pin. Here’s how one would do it. If this code is inserted at the beginning of main() then you can use your oscilloscope to look at the clock signal directly.
Code Example 3: Transmitting Data Using the UART
The program below will transmit a single value, in this case 0x55, over the UART. This is a very simple program that doesn’t use interrupts or check any of the possible error flags, but it gives an idea of how to set up the device. For different baud rates you can adjust the UARTCLKDIV value. The “UART Fractional Divider Register” can be used to generate the proper baud rate as well (see section 13.5.15 of the LPC11xx User Manual).
Figure 6: Example scope shot of 19.2k baud transmission of hex value 0x55 using UART code given above.
Code Example 4: Receiving Data Using the UART
The program below demonstrates how data can be received through the serial port. Note that this code will only work if the TX pin (PIO1_7) and RX pin (PIO1_7) are shorted together. As always this is a very simple program that doesn’t use interrupts or check any of the possible error flags, but it shows a simple UART application for receiving data. Inside the main while loop, the program first transmits a byte (after incrementing it). After a for loop delay, the program checks the UART Line Status Register's "Receiver Data Ready" bit to see if a byte has been received. If a byte has been received it breaks out of the while loop and updates the data variable with the new byte. If a scope is placed on the loop back data line you can see each byte being transmitted. You can also easily see the data being incremented. If one is using the OM11049,598 board for development, the shorting of the RX and TX pins can be easily accomplished with a small jumper between the two vias on the edge of the PCB.
Code Example 5: Using the Analog to Digital Converter (ADC)
Another essential peripheral for most embedded applications is the analog to digital converter. The program below will read a value from ADC channel 0 (pin 32 on the QFP package). This code snippet is a little longer because the UART code is retained so that the ADC data can be sent out on the UART to look at on an oscilloscope. Generally, the ADC is one of the simpler peripherals to use. There are only 5 registers to contend with in the ADC unit. For more examples of how to use other channels of the ADC unit click here for a word document or here for a plain text file.
Code Example 6: Transmitting with Synchronous Serial Port (SSP/SPI)
Here is a working example of how to set up and transmit using the SSP/SPI bus. The ADC is only included to provide data to output through the SPI bus.
Figure 7: This oscilloscope screenshot show the SCLK signal (in yellow) and the MOSI signal (in blue).
Code Example 7: Setting Up the 16bit Timer for PWM
The following is a code snippet showing how to set up 16 bit timer 0 for PWM operation on PIO0_8 (pin 27 of the 48 pin LQFP package). In this case, the value for the period of the PWM signal is loaded into LPC_TMR16B0->MR1. The duty cycle is loaded into LPC_TMR16B0->MR0.
Code Example 8: Transmitting with I2C
This code snippet shows an example of a simplistic I2C communication. This code was written to allow The LXP11XX part on the OM11049,598 PCB to toggle some LEDs using an I2C compatible PCA9532 LED driver. This part is available on the EA-XPR-021 base board, and it was on this base board that this code was tested. As usual this code doesn't check for errors or I2C states other than the ones expected in normal error-free operation. Still, it is a starting place. It should be noted that the author found it quite difficult to get this peripheral up and running using nothing but the datasheet. The compiler also seemed to be finicky about the way bits were set in the registers. For instance, in the code below there is a line that contains the following C statement: LPC_I2C->CONCLR = 0x28; The datasheet says that writing zero's to this register has no effect, so it would seem that this statement could be written: LPC_I2C->CONCLR |= 0x28; However, the author found that this was not true. The code will only work with the former statement. If a reader knows why this is the case, please login and post your comments for everyone to see.
This webpage is a project started and maintained by the applications engineering staff at Digi-Key. It is our attempt to provide free support to engineers, hobbyists, entrepreneurs, and other tech minded folks to assist you with your work. In many ways, adding content to this website is the best part of our job. However, it isn't our only job. Like all applications engineers we are expected to show profit for the Digi-Key. So if you have used any of our content to help you select or use Digi-Key products, let us know about it. Parts distributors crave your feedback with the same zeal and intensity that I crave pizza. Digi-Key is no exception. If your project meets certain criteria, we may be able to send you engineering samples. Okay, end of lecture.
To get in touch with us call 1.800.344.4539. Additionally, all the authors of the eewiki can also be contacted by email. Just send an email to firstname.lastname@example.org and mention the author in the subject line.
Want a production part quote right now? Send me the information below (example).
Engineer Name and Contact Info
Estimated Date of Production
Estimated Annual Usage of Part
Part Number to be quoted