April
2005, Issue 177
Simple
USB Data Acquisition
EMBEDDED
SOFTWARE
Before
writing actual LPC2138 application code, the device
needs to be set up after it’s powered on. Fortunately,
most IDEs will either set this up for you or provide
some kind of boot assembly code to handle the task.
For this particular project, I used the evaluation version
(16-KB code size limitation) of the Keil µVision3 environment.
I was pleasantly surprised with its boot-up implementation.
The graphical configuration wizard allows you to modify
the proper setup registers for your application. This
made the boot and start-up process transparent and allowed
me to focus on the application itself.
Let’s
look at the LPC2138’s PLL setup as an example. To change
the PLL multiplier value on the LPC2138, you must perform
a few extra steps after writing the new multiplier and
control values to the PLLCFG and PLLCON registers. These
steps entail writing 0xAA and then 0x55 to the PLL feed
register (PLLFEED). This action loads the PLL control
and configuration information from the PLLCON and PLLCFG
registers into the shadow registers that actually affect
PLL operation. It’s basically a good way to prevent
accidental changing of the PLL value. This code implementation
is taken care of with the provided boot code in µVision3.
Punching in the desired multiplier in the GUI automatically
updates the boot code. I learned this the hard way in
a different IDE when designing with the LPC2106. The
point is that using the graphical configuration tool
is an easy and fast way to set up the microcontroller
so you can start working on your application.
Now
that the boot up code is taken care of, let’s concentrate
on the main application. I chose C language over the
native ARM assembly language to write the driver and
application code. So, the next step involved writing
a C code driver for a timer interrupt, an A/D scan,
and the UART. Fortunately, the example C code that came
with the µVision3 IDE had examples for all the peripherals.
I modified and used them.
The
code for each peripheral was extremely straightforward
and easy to understand and integrate. Creating the application
code, including the C code for each peripheral, resulted
in the code shown in Listing 1.
In this code a timer match interrupt occurs from the
interval timer, and then the AIN-1 A/D channel is read
to sample the analog output voltage from the LM60 temperature
sensor. The analog temperature data is then masked because
only 10 bits are valid because of the 10-bit A/D resolution.
Now the reading is ready to be sent out the serial port
via the UART through the printf statement. Listing 1
is all the code you need to read the LM60 temperature
sensor every few minutes and send the raw ASCII-converted
A/D result out of the serial port.
You
must download code to the board and begin debugging
at this point. I used the ULINK JTAG debugger, which
integrates nicely with the Keil µVision3 IDE. The debugger
connects to the MCB2130 debug connector and communicates
directly with the ARM7 core inside the LPC2138 via its
EmbeddedICE logic (see Photo 1).
The
typical debug options are available in µVision3. Single
stepping, watch windows, break points, and memory snooping
are all possible with the LPC2138. An interesting item
in the µVision3 IDE is the ability to interact with
LPC2138 peripherals while the program is idle. A separate
GUI can be opened for the various LPC2138 peripherals
that allows for interaction and control of them. Things
like manually scanning the LPC2138’s A/D converter and
flipping of one of its GPIO bits are possible. A couple
of the windows are shown in Photo 2. This is a good
way to get to know some of the peripherals and their
associated registers on the LPC2138. Given all these
features, I quickly downloaded code to the board, ran
it, and debugged it.
|


(Click
here to enlarge)
|
Photo
2—The debug peripheral windows in the Keil debugger
were useful when I was experimenting with the ADC
and GPIO port bits. They enabled me to scan the
ADC for the analog temperature value prior to connecting
up the GUI and to alter the state of the GPIO bits
at will. This eliminated the need for writing special
test code. |