Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
9 views42 pages

Unit 3 Timer

LPC2148 is a 32-bit microcontroller from NXP Semiconductors based on the ARM7TDMI-S family, featuring 32kB of RAM and 512kB of flash memory, making it beginner-friendly despite being considered obsolete. It includes two 32-bit GPIO ports (PORT0 and PORT1) for interfacing with external components, and the GPIO functionalities are managed through specific registers for input/output control. Additionally, the document discusses the Phase Locked Loop (PLL) configuration for clock signal generation, detailing the relationship between external oscillator frequency and CPU clock frequency.

Uploaded by

Shashank Patil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views42 pages

Unit 3 Timer

LPC2148 is a 32-bit microcontroller from NXP Semiconductors based on the ARM7TDMI-S family, featuring 32kB of RAM and 512kB of flash memory, making it beginner-friendly despite being considered obsolete. It includes two 32-bit GPIO ports (PORT0 and PORT1) for interfacing with external components, and the GPIO functionalities are managed through specific registers for input/output control. Additionally, the document discusses the Phase Locked Loop (PLL) configuration for clock signal generation, detailing the relationship between external oscillator frequency and CPU clock frequency.

Uploaded by

Shashank Patil
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

What is LPC2148 and GPIO

LPC2148 is a 32-bit Microcontroller based on the ARM7TDMI-S Family. It is manufactured by


NXP Semiconductors (formerly Philips) and is one of the widely used and highly successful
ARM7 based Microcontroller.

Even though ARM7 family is considered obsolete with the introduction of many advanced
processors and controllers, it is one of the best and easiest microcontrollers to work around for
beginners in ARM based microcontrollers.

Before going in to the details of the input/output pins, we’ll see some of the key features of the
LPC2148 microcontroller.

 LPC2148 is a -bit microcontroller based on ARM7 family (ARM7TDMI-S to be specific)


and is available in a 64 pin LQFP Package (Low Profile Quad Flat Package).
 It has an on-chip static RAM of 32kB and an on-chip flash memory of 512kB.
 LPC2148 has an on-chip boot loader software that can be used to program the
microcontroller using the feature of In-System Programming.
 It also has the feature of in-Application Programming using which the user can program the
microcontroller without using the boot loader software.
 It has an embedded in-circuit emulator that helps in real time debugging.
 LPC2148 has two 10-bit ADCs (ADC0 and ADC1) of Successive Approximation type.
 It also has a 10-bit DAC of Resistor String type.

Other features can be found in the official datasheet and user manual.

General Purpose Input Output (GPIO) pins of a microcontroller are the first thing we need to
learn before starting its embedded programming as input/output pins are the only way to
interface with the microcontroller. GPIO pins can be used for driving loads, reading digital and
analog signal, controlling external components, generating triggers for external devices etc.

LPC2148 has two IO ports namely PORT0 (P0) and PORT1 (P1). These two IO ports are of 32-
bit wide and are provided by the 64 pins of the microcontroller.

The naming convention of the I/O pins on the LPC2148 Microcontroller is Pa.bc where ‘a’ is the
number of the port i.e. 0 or 1 (as LPC2148 has only two ports) and ‘bc’ is the number of the pin
in the port a. For example, P0.1 indicates pin number 1 of PORT0 and P1.10 indicates pin
number 10 of PORT1.

PORT0 is a 32-bit wide input/output port with dedicated direction control bits for each physical
pin. Out of the 32 pins, 28 pins can be used as general purpose bidirectional I/O pins. Pin P0.31
is an output only pin. Pins P0.24, P0.26 and P0.27 of PORT0 are not available.

PORT1 is also a 32-bit wide input/output port. In PORT1, pins P1.0 to P1.15 are not available
and pins P1.16 to P1.31 are the available general purpose input/output pins.

Most of the pins in both the I/O ports of the LPC2148 have more than one function i.e. they are
multiplexed with different functions. For example, Pin 19 of the LPC2148 has three functions
namely P0.0, a general purpose I/O pin, TXD0, the transmitter O/P for UART0 and PWM1, the
pulse width modulator O/P 1.

1| Prepared By: U. U. Deshpande


At any point of operation, each pin can have a single function and the function can be selected
with the help of three Configuration Registers which control the multiplexers to allow
connection between the external pin and the on-chip peripheral.

The configuration register is called PINSEL and is classified in to three registers: PINSEL0,
PINSEL1 and PINSEL2. These configuration registers are of 32-bit wide. Any pin on the
LPC2148 can have a maximum of 4 functions. Hence in order to select one of the four functions,
two corresponding bits of the PINSEL register are needed. So, a 32-bit PINSEL register can
control 16 pins with 2-bits to control each pin.

PINSEL0 controls PORT0 pins P0.0 to P0.15, PINSEL1 controls PORT0 pins P0.16 to P0.31
and PINSEL2 controls PORT1 pins P1.16 to P1.31.

The following table shows the PINSEL0 and corresponding functions on the PORT0.

The default function of all the Pins is GPIO. But it is a good programming practice to mention
“PINSEL0=0” in order to select the GPIO function of the Pins.

2| Prepared By: U. U. Deshpande


GPIO function is the most frequently used functionality of the microcontroller. The GPIO
functions in both the Ports are controlled by a set of 4 registers: IOPIN, IODIR, IOSET and
IOCLR.

IOPIN: It is a GPIO Port Pin Value register and can be used to read or write values directly to
the pin. The status of the Pins that are configured as GPIO can always be read from this register
irrespective of the direction set on the pin (Input or Output).
The syntax for this register is IOxPIN, where ‘x’ is the port number i.e. IO0PIN for PORT0 and
IO1PIN for PORT1.

IODIR: It is a GPIO Port Direction Control register and is used to set the direction i.e. either
input or output of individual pins. When a bit in this register is set to ‘0’, the corresponding pin
in the microcontroller is configured as Input. Similarly, when a bit is set as ‘1’, the
corresponding pin is configured as Output.
The syntax for this register is IOxDIR, where ‘x’ is the port number i.e. IO0DIR for PORT0 and
IO1DIR for PORT1.

IOSET: It is a GPIO Port Output Set Register and can be used to set the value of a GPIO pin that
is configured as output to High (Logic 1). When a bit in the IOSET register is set to ‘1’, the
corresponding pin is set to Logic 1. Setting a bit ‘0’ in this register has no effect on the pin.
The syntax for this register is IOxSET, where ‘x’ is the port number i.e. IO0SET for PORT0 and
IO1SET for PORT1.

IOCLR: It is a GPIO Port Output Clear Register and can be used to set the value of a GPIO pin
that is configured as output to Low (Logic 0). When a bit in the IOCLR register is set to ‘1’, the
corresponding pin in the respective Port is set to Logic 0 and at the same time clears the
corresponding bit in the IOSET register. Setting ‘0’ in the IOCLR has no effect on the pin.
The syntax for this register is IOxCLR, where ‘x’ is the port number i.e. IO0CLR for PORT0 and
IO1CLR for PORT1.

Note: An important note to remember is that since the LPC2148 is a 32-bit microcontroller, the
length of all the registers mentioned is also 32-bits. Each bit in the above mentioned registers is

3| Prepared By: U. U. Deshpande


directly linked to the corresponding pin in the microcontroller i.e. bit ‘a’ in IO0SET corresponds
to Pin ‘a’ in the PORT0.
Registers in LPC2148 follow Big Endian format i.e. bit 0 is the LSB on the extreme right of the
register and bit 31 is the MSB on the extreme left of the register.
Another important note is that when reset, all the pins are set as GPIO pins and the direction of
each pin is set as Input.
Now, we’ll see how to use the above mentioned registers in programming. First, is to set the
direction of a pin. For example, if we want to set 4th pin of PORT0 i.e. P0.3 as output, then it can
be set in various ways as shown below.

Method 1: IO0DIR = (1<<3);


This is a direct assignment method where the binary value (1) is set directly on the pin. All the
other pins are set to 0. This method should be avoided as the value is directly being assigned in
the register and while P0.3 is assigned as ‘1’, all the other pins are forced to be assigned ‘0’.
An alternative to this method is ORing the register and then assigning the value. This can be
done in two ways.

Method 2: IO0DIR | = 0x00000008;


In this method, the hexadecimal value of the register is assigned after ORing the register with
itself. In this way, the other pins other than the desired pin (P0.3 in this case) are not affected.
This method is useful if we want to assign many pins without affecting the other pins.

Method 3: IO0DIR | = (1<<3);


This is similar to the above method except that only a single pin is affected.
Other registers can also be set using the same methods. Now, we’ll see an example of setting pin
15 of PORT0 i.e. P0.15 as output and drive the pin High.

For this we need to use two registers: IODIR and IOSET.


IO0DIR | = (1<<15); // Configuring P0.15 as output.
IO0SET | = (1<<15); // Make the O/P pin P0.15 as High

We’ll see another example where pin 11 of PORT0 is set as output and the output of this pin is
set to logic 1 and then to logic 0.

For this we need to use three registers: IODIR, IOSET and IOCLR.
IO0DIR | = (1<<11); // Configuring P0.11 as output.
IO0SET | = (1<<11); // Make the O/P pin P0.11 as High.
IO0CLR | = (1<<11); // Make the O/P pin P0.11 as Low.

Now, we’ll see an example where more than one pin has to be set as output and the value of that
pin must be HIGH. Consider pins 7 and 14 of PORT0 (P0.7 and P0.14).

IO0DIR | = (1<<7) | (1<<14); // Configuring pins P0.7 and P0.14 as output.


IO0SET | = (1<<7) | (1<<14); // Make the O/P of pins P0.7 and P0.14 as High.

Once we have seen how to set the direction of pins, setting the pin as High or Low, now we’ll
jump into real time embedded programming. Similar to “Hello, World” program in C Language,
blinking an LED is the basic program in embedded system.

4| Prepared By: U. U. Deshpande


The IDE we are going to use for the development of LPC2148 based projects is Keil µVision.
All the registers for LPC214X series of microcontrollers are defined in the “lpc214x.h” header
file.

Examples: Configuring & initializing GPIO pins


PINSEL1 &= ~(0xFF); // configure pins from P0.16 to P0.19 as GPIO
IO0DIR |= (0xF<<16); // set pins P0.16 – P0.19 to output function
IO0SET |= (1<<16)|(1<<18); // set pins P0.16 & P0.18 of Port-0 HIGH
IO0CLR |= (1<<16); // reset logic level of pin P0.16 of Port-0 LOW

In this example, we’ll blink the LEDs repeatedly that are connected to PORT1 pins of the MCU.
#include <lpc214x.h>
int delay;
main ()
{
PINSEL2 = 0x00000000;
IO1DIR = 0xFFFFFFFF; // All the pins of PORT1 are configured as Output
while(1)
{
IO1SET |= (1<<15); // Set Logic 1 to all the PORT1 pins i.e. turn on LEDs
for (delay = 0; delay<50; delay++);
IO1CLR |= (1<<15); // Set Logic 0 to all the PORT1 pins i.e. turn off LEDs
for (delay = 0; delay<50; delay++);
}
}

The program is self-explanatory. First, the PORT1 pins are configured as outputs using IO1DIR
register. Then in an infinite loop, the pins (or LEDs connected to them) are turned ON using
IO1SET register and turned OFF using IO1CLR register. A delay is introduced between the
turning ON and OFF of the LEDs using a “for” loop, so that the blinking of LEDs is visible.

5| Prepared By: U. U. Deshpande


Introduction to PLL
Phase Locked Loop or PLL is a system that generates a clock signal with reference to an input
signal generally from a crystal oscillator. In this tutorial, we will see how to configure the PLL in
LPC2148 and use it as a clock generator.

Before going in to discussion about PLL, we will see some basics of clock signal generation in
LPC2148 and crystal oscillator.

LPC2148 has an on – chip oscillator that operates in coordination with an external crystal
oscillator in the range of 1 MHz to 25 MHz. If FOSC is the frequency of the output of the external
oscillator and CCLK is the clock frequency of the processor, then FOSC and CCLK are same
unless we are using the PLL.

When we are using PLL, the external clock frequency from crystal oscillator is limited to the
range of 10 MHz to 25 MHz. This input clock frequency is multiplied up with a multiplier and a
current controller oscillator (CCO) to a range of 10 MHz to 60 MHz. The maximum operating
frequency in LPC214X series of MCUs is limited to 60 MHz. Hence, the maximum output of the
PLL is 60 MHz.

There are two PLL Modules in LPC214X series of MCUs: PLL0 and PLL1. PLL0 is used to
generate the system clock and PLL1 is used to generate clock signal for USB. Both PLL0 and
PLL1 accept the input clock signal in the range of 10 MHz to 24 MHz but the output of PLL0 is
multiplied to 10 MHz to 60 MHz whereas the output of PLL1 is fixed at 48 MHz for USB clock.
In this tutorial, we will focus only on PLL0 as it is the main clock signal which acts as the CPU
clock and also goes to on – chip peripherals. As said earlier, the input clock frequency from
external crystal is multiplied up with the help of a multiplier and a CCO. The multiplier can be
any integer in the range of 1 to 32. Practically speaking, the multiplier value can’t be more than 6
as the upper frequency of the CPU is limited to 60 MHz.

The current controlled oscillator or CCO operates in the frequency range of 156 MHz to 320
MHz. In order to keep the CCO in this range, an additional divider in the PLL is used. The
divider may be set to divide by 1, 2, 4, or 8 to generate the output clock frequency.
Before going further in to configuring the PLL, we will see some frequently used symbols,
formulae and standard values as mentioned in the data sheet.
Symbols
FOSC Frequency of the crystal oscillator
FCCO Frequency of Current Controlled Oscillator (CCO)
CCLK CPU Clock frequency (PLL Output frequency)
M PLL Multiplier value (set using MSEL bits in PLLCFG register)
P PLL Divider value (set using PSEL bits in PLLCFG register)
PCLK Peripheral clock from CCLK

6| Prepared By: U. U. Deshpande


Formulae
The frequency of CPU clock or the output of the PLL is
CCLK = M x FOSC or CCLK = FCCO / (2 x P)
The frequency of CCO is
FCCO = CCLK x 2 x P or FCCO = FOSC x M x 2 x P
Standard Values (when PLL is used)

 The range of FOSC is 10 MHz to 25 MHz


 The range of CCLK is 10 MHz to FMAX (60 MHz for LPC214x MCUs)
 The range of FCCO is 156 MHz to 320 MHz

Setting up PLL
Note: In order to generate the desired clock frequency using PLL, we need to manipulate the
values of multiplier and divider. This has to be done with extreme caution as the output of the
PLL acts as the main clock signal for the CPU and is also given to other on – chip peripherals
that operate on clock signal.

If the PLL is miss – configured (accidently or deliberately), the microcontroller may not work
and the user is responsible.

Coming to the setting up the PLL, to avoid the accidental miss – configuration of the PLL, we
need to use a Feed sequence. A feed sequence is initialized whenever we are trying to configure
PLL. Feed sequence acts as a key to unlock the PLL configuration.

A special PLL related register called “PLL0FEED” is used to setup the feed sequence. In order
to set the feed sequence, the PLL0FEED register must be assigned with two fixed values i.e.
0XAA and 0X55.

The code for initiating the feed sequence is


PLL0FEED = 0XAA;
PLL0FEED = 0X55;

Once we initialized the feed sequence successfully, we can proceed with configuring the PLL.
For this, we need to know about the other PLL register that we will use.

PLL Control Register (PLLCON): The PLL Control Register or PLLCON register contains the
bits that re used to “Enable” and “Connect” the PLL. The first bit in the PLLCON register is the
PLL Enable (PLLE) bit and the second bit is the PLL Connect (PLLC) bit.

Enabling the PLL means allowing it to lock the values of multiplier and divider. Connecting the
PLL means allowing the CPU and other on – chip peripherals to use the output of the PLL as
their clock signal.

The syntax of this register is PLLxCON, where ‘x’ is the PLL module i.e. PLL0CON for PLL0
and PLL1CON for PLL1.
Note: The similar nomenclature will be followed in the rest of the article where ‘x’ in any PLL
related register is used to indicate the PLL block i.e. ‘x’ = 0 for PLL0 and ‘x’ = 1 for PLL1.

7| Prepared By: U. U. Deshpande


PLL Configuration Register (PLLxCFG): The PLL Configuration Register is used to store the
multiplier and divider values of the PLL. The values in the PLLCFG register will come in to
effect only when the correct feed sequence is given.
The first five bits in the PLLCFG register, which are called MSEL, are used to store the value of
the Multiplier (M). The next two bits, which are called PSEL, are used to store the Divider (P)
value.

PLL Status Register (PLLxSTAT): The PLL Status Register is a read – only register that
provides the PLL parameters that are set using other PLL registers. If gives details about MSEL
(Multiplier), PSEL (Divider), PLLE (PLL Enable), PLLC (PLL Connect) and PLOCK.
The main bit we must focus in PLLSTAT register is the 11 th bit i.e. PLOCK. The PLOCK bit
indicates the lock status of the PLL. The PLOCK bit becomes ‘1’ only when the PLL is locked
on to the desired frequency.
The following order of settings must be followed in order to configure the PLL for a desired
frequency.

 Setup PLL
 Feed Sequence for locking PLL
 Wait for PLL to lock to desired frequency
 Connect PLL
 Feed Sequence for setting PLL as system clock
We have seen earlier how to apply the Feed Sequence. Now we will move further and see how to
configure PLL.

Procedure for determining PLL Settings


We need to perform the following steps for PLL0.

1. Choose the desired system frequency (CCLK). The system clock may be based on
processor throughput, UART baud rates, etc.
2. Select the input frequency for the crystal oscillator (FOSC). The system clock (CCLK)
must be a multiple of oscillator frequency (FOSC).
3. Calculate the value of Multiplier (M) and configure the MSEL bits. From the formulae
mentioned above, M = CCLK / FOSC (The range of M is 1 to 32). From this ‘M’ value, we
need to write the MSEL bits in PLL0CFG register as “M-1”.
4. Calculate the value of Divider (P) and configure the PSEL bits. Divider is chosen such that
the frequency of CCO (FCCO) is in the limits (156 MHz to 320 MHz). The value of ‘P’
can be 1, 2, 4, or 8.

Let us assume that the CPU frequency is at the maximum possible value i.e. 60 MHz. We will
calculate the values of P and M with this frequency in mind.
First, we will see the possible values of PSEL based on different ‘P’ values.
P Binary Value in PSEL (Bits 5 and 6 in PLL0CFG)
1 00
2 01
4 10
8 11

8| Prepared By: U. U. Deshpande


Since CCLK = 60 MHz, we can calculate the value of P as follows. The equation to calculate P
is given by,
P = FCCO / (2 X CCLK)

We know that the range of FCCO is 156 MHz to 320 MHz.


Substituting FCCO = 156 MHz, we get P = 156 MHz / (2 X 60 MHz) = 1.3.
Substituting FCCO = 320 MHz, we get P = 320 MHz / (2 X 60 MHz) = 2.67.
Since the value of ‘P’ must be an integer, the integer between 1.3 and 2.6 is ‘2’.
As we got the value of ‘P’ as ‘2’, the value in the PSEL bits should be ‘01’.

We will now calculate the value of ‘M’. From the above mentioned formulae, we can calculate
the value of ‘M’ using the following formula.
M = CCLK / FOSC

The following table indicates a list of possible crystal oscillator values along with the values of
‘M’, ‘MSEL’, ‘P’, ‘PSEL’ and the value in the PLL0CFG register.
FOSC M Value in MSEL (M -1) P Value in PSEL Value in PLL0CFG
5 MHz 12 11 = 0XB 2 01 0X2B
10 MHz 6 5 = 0X5 2 01 0X25
12 MHz 5 4 = 0X4 2 01 0X24
15 MHz 4 3 = 0X3 2 01 0X23
20 MHz 3 2 = 0X2 2 01 0X22

Peripheral Clock (PCLK)


The clock signal from the PLL is given to CPU as its clock. The PLL signal must also be
supplied to other on – chip peripherals. By default, the peripheral clock (PCLK) runs at a quarter
speed of the CCLK. The relation between the CPU clock and peripheral clock can be configured
by using a special register called “VPBDIV” (as per Keil Compiler).
The following image shows the block diagram of PLL, CCLK and PCLK.

9| Prepared By: U. U. Deshpande


The value in the VPBDIV register determines the PCLK value. The following table shows the
possible values of VPBDIV and the corresponding PCLK values.
VPBDIV = 0x00 PCLK is ¼ of CCLK
VPBDIV = 0x01 PCLK is equal to CCLK
VPBDIV = 0x02 PCLK is ½ of CCLK
VPBDIV = 0x03 Reserved. No effect.

We have seen all the registers, settings and necessary calculations in order to configure PLL0.
For more information about this, we can look up to the data sheet and user manual of LPC214x
series of MCUs.

Now, we’ll see an example program for configuring the PLL0 so that the CPU Clock (CCLK)
and the Peripheral Clock (PCLK) must run at 60 MHz with an external crystal oscillator
operating at 12 MHz.
Note: 12 MHz is the most common value for crystal oscillator in many microcontroller
development boards. If the development you are using has a different crystal oscillator (for some
strange reason), then we need to consider the values of ‘M’ and ‘P’.

#define PLOCK 0x00000400


int main(void)
{
/* PPLE = 1 and PPLC = 0 so PLL0 will be enabled but not connected. */
PLL0CON = 0x01;
/* PLL0CFG is set as per the table mentioned above. */
PLL0CFG = 0x24;
/* Feed Sequence for locking PLL0 to desired frequency */
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
/* Check whether the PLL0 has locked on to the desired frequency by reading the lock bit
in the PPL0STAT register */
while( !( PLL0STAT & PLOCK ));
/* Now enable(again) and connect the PLL0 */
PLL0CON = 0x03;
/* Feed Sequence for connecting the PLL0 as system clock */
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
/* Now the System Clock is running @ 60 MHz! Next step is to set the Peripheral Clock at same
frequency as System Clock */
VPBDIV = 0x01;
while(1);
}

10 | Prepared By: U. U. Deshpande


Interrupts in LPC2148

11 | Prepared By: U. U. Deshpande


Interrupts in LPC2148
The main purpose of any microcontroller is to accept input from input devices and accordingly
drive the output. Hence, there will be several devices connected to a microcontroller at a time.
Also, there are many internal components in a microcontroller like timers, counters etc. that
require attention of the processor.

Since all the devices can’t obtain the attention of the processor at all times, the concept of
“Interrupts” comes in to picture. An Interrupt, as the name suggests, interrupts the
microcontroller from whatever it is doing and draws its attention to perform a special task. The
following image depicts the procedure involved in Interrupts.

In the event of an interrupt, the source of the interrupt (like a Timer, Counter etc.) sends a special
request to the processor called Interrupt Request (IRQ) in order to run a special piece of code.
The special code or function is called as Interrupt Service Routine (ISR).

From the above figure, the CPU executes its normal set of codes until an IRQ occurs. When the
IRQ signal is received, the CPU stops executing the regular code and starts executing the ISR.
Once the execution of the ISR is completed by the CPU, it returns back to execution of the
normal code.

Vectored Interrupt Controller (VIC) handles the interrupts in LPC214x series of MCUs. It can
take up to 32 Interrupt Requests. The interrupts in LPC2148 microcontroller are categorized as
Fast Interrupt Request (FIQ), Vectored Interrupt Request (IRQ) and Non – Vectored Interrupt
Request. All the interrupts in LPC214x have a programmable settings i.e. the priorities of the
Interrupts can be dynamically set.

Of the three categories, the FIQ requests have the highest priority, Vectored IRQ requests have
the medium priority and non – vectored IRQ requests have the least priority.

When we are talking about “Vectored” and “Non – Vectored” IRQ requests, we are actually
talking about the address of the ISR. In case of Vectored IRQ requests, the CPU has a knowledge
of the ISR. A special table called Interrupt Vector Table (IVT) contains all the information about
the Vectored IRQ. This information can be about the source of the interrupts, ISR address of the
IRQ requests etc.

11 | Prepared By: U. U. Deshpande


So, each Vectored IRQ has its own unique ISR address. Out of the possible 32 interrupt requests,
16 interrupt requests can be defined as Vectored IRQ. In this 16 slots, any of the 22 interrupts
that are available in LPC2148 can be assigned. In the 16 Vectored IRQ slots, slot 0 has the
highest priority while slot 16 has the least priority.

In case of Non – Vectored IRQ, as the name itself indicates, the CPU isn’t aware of either the
source of the Interrupt or the ISR address of the Interrupts. In this case, the CPU must be
provided with a default ISR address. For handling Non – Vectored IRQ requests, a special
register called “VICDefVectAddr” is available in LPC2148. The address of the default ISR must
be given in this register by the user in order to handle the Non – Vectored IRQ requests.

Note: All the Non – Vectored IRQ Requests have the same ISR address which is defined in the
VICDefVectAddr register.
 Programs can handle 1 FIQ, 16 VIRQ, 1 NVIRQ (total 18) interrupts.

Interrupt Related Registers in LPC2148


There are many registers corresponding to Vectored Interrupt Controller (VIC). These registers
are used to either configure the interrupts or read the status of the interrupt. The important thing
to remember about all the registers related to VIC is that each bit is associated with a particular
interrupt source in all the VIC registers. Bit 0 is associated with Interrupt corresponding to
Watch dog Timer and it is same in all VIC related registers.
The following table shows the list of 22 interrupt sources in LPC2148 and their corresponding
Bit position in VIC registers.
Bit# 22 21 20 19 18 17 16 15 14 13 12 11

SPI1/SS
IRQ USB AD1 BOD I2C1 AD0 EINT3 EINT2 EINT1 EINT0 RTC PLL
P

12 | Prepared By: U. U. Deshpande


Bit# 10 9 8 7 6 5 4 3 2 1 0
ARMCo ARMCo
IRQ SPI0 I2C0 PWM UART1 UART0 TIMER1 TIMER0 N/A WDT
re1 re0

The following is the list and description of registers that are associated with Interrupts in
LPC214x series MCUs. The registers mentioned here are few important of the total available
VIC Registers and are also in best order to start learning about VIC.

 Software Interrupt Register (VICSoftInt): Software Interrupt Register is used to manually


generate the interrupts using software i.e. code before the masking by external source. When
a bit is set with 1 in the VICSoftInt register, the corresponding interrupt is triggered even
without any external source.
 Software Interrupt Clear Register (VICSoftIntClear): Software Interrupt Clear Register is
used to clear the bits set by Software Interrupt Register. When a bit is set to 1 in this
register, the corresponding bit in the Software Interrupt Register is cleared and hence
releasing the forced interrupt.
 Interrupt Enable Register (VICIntEnable): Interrupt Enable Register is used to enable
the interrupts that can later contribute to either FIQ or IRQ. When a bit is set to 1, the
corresponding interrupt is enabled. As this is a read / write register, when this register is
read, “1” indicates that the external interrupt request or software interrupts are enabled.
 Interrupt Enable Clear Register (VICIntEnClear): Interrupt Enable Clear Register is used
to clear the bits set by the Interrupt Enable Clear Register i.e. it is used to disable the
interrupts. When a bit is set with “1”, the register allows the software to clear the
corresponding bit in the Interrupt Enable Register and thus disabling the interrupt for that
particular request.
 Interrupt Select Register (VICIntSelect): Interrupt Select Register is used to classify each
of the 32 interrupts as either FIQ or IRQ. When a bit in this register is set to “0”, then the
corresponding interrupt (as shown in the above table) will be made as an IRQ. Similarly,
when a bit is set to “1”, the corresponding interrupt is made as FIQ.
 IRQ Status Register (VICIRQStatus): Interrupt Status Register is used to read out the status
of the interrupts that enabled and declared as IRQ. Both Vectored and Non – Vectored IRQ
are read out. When a bit is read as “1”, then the corresponding Interrupt is enabled and
defined as IRQ.
 FIQ Status Register (VICFIQStatus): This register is similar to IRQ Status Register
(VICIRQStatus) except it reads the status of interrupts that are enabled and defined as FIQ.
 Vector Control Registers (VICVectCntl0 – VICVectCntl15): Vector Control Registers are
used to assign slots to different interrupt sources that are classified as IRQ. There are 16
Vector Control Registers and each register controls one of the 16 Vectored IRQ slots.
VICVectCntl0 (Slot 0) has the highest priority while VICVectCntl15 (Slot 15) has the least
priority. The first 5 bits in the Vector Control Registers (Bit 0 – Bit 4) contains the number
of the interrupt request. The 5th bit (Bit 5) is used to enable the Vectored IRQ Slot. The
following tables are be used to show the interrupt source and their corresponding Source
Number in Decimal format.
Interrupt Source Source Number in Decimal
WDT 0
N/A 1
ARMCore0 2

13 | Prepared By: U. U. Deshpande


ARMCore1 3
TIMER0 4
TIMER1 5
UART0 6
UART1 7
PWM 8
I2C0 9
SPI0 10
SPI1 11
PLL 12
RTC 13
EINT0 14
EINT1 15
EINT2 16
EINT3 17
ADC0 18
I2C1 19
BOD 20
ADC1 21
USB 22

For example, if we want to assign Slot 0 to Timer0 IRQ, then the Vector Control Register must
be declared as follows:
VICVectCntl0 = 0x20 | 4;
Note: When a Vectored IRQ is disabled in any of the VICVectCntl0 – 15 registers, it will not
disable the actual interrupt but the Vectored IRQ is changed to Non – Vectored IRQ.

 Vector Address Registers (VICVectAddr0 – VICVectAddr15): Vector Address Registers


are used to hold the addresses of the ISR of the 16 Vectored IRQ slots. If Slot 0
(VICVectCntl0) is assigned to TIMER0 IRQ, then the address for the interrupt function
must be assigned to VICVectAddr0.
 Default Vector Address Register (VICDefVectAddr): Default Vector Address Register
holds the address of the ISR for Non – Vectored IRQs. This address acts as the default or
common ISR address when a Non – Vectored IRQ occurs.
 Vector Address Register (VICVectAddr): This is a different and single register and must not
be confused with Vector Address Registers (VICVectAddr0 – VICVectAddr15). It is a read
/ write register and when the data is read from this register, it returns address of ISR.
Writing a value to this register indicates the VIC that the execution of the current interrupt is
finished. Hence, this register is written with a dummy value at the end of the ISR to indicate
the end of execution.

14 | Prepared By: U. U. Deshpande


Programming VIC registers:
O Program VICIntSelect: Set / reset the bits for FIQ / IRQ classification
O Program VICVectCtrlx: Assign VIRQ slot ‘x’ to IRQ classified interrupt
O Program VICVectAddrx: Write ISR addr of VIRQ interrupt assigned to slot ‘x’
O Program VICIntEnable: Enable interrupts

Handling FIQ interrupts:


O Branch instruction at 0x0000001C uses address of FIQ handler directly and goes to FIQ
routine. This reduces interrupt latency.
O If more than one interrupt are assigned as FIQ, the handler routine identifies the source
of interrupt. This increases interrupt latency.
O]Executes codes respective of identified interrupts.
O Clears flags set by peripherals in their interrupt registers
O End of interrupt.

Handling IRQ interrupts:


O On interrupt, processor executes branch instruction from interrupt vector table at 0x
00000018 and branches to IRQ handler routine
O Reads VICVectAddr reg that holds address of highest priority pending VIRQ Slot-x
interrupt. If no slot is assigned, it holds address of default vect address
O Branches to handler routine.
O Reads interrupt register of the peripheral, identifies actual source, executes codes
respective of the interrupt.
O Clears interrupt flags set by peripherals in their interrupt registers.
O Writes a dummy word into VICVectAddr register to indicate EoI, to clear respective
interrupt in VIC interrupt priority hardware.
O Returns back to interrupted program, re-enables interrupts.

Configuring Interrupts in LPC2148


Now that we have seen the list and functionalities of different registers associated with VIC, we
will see how to configure interrupts and define the respective ISRs. For that, first we will see
how to properly define the ISR function so that the compiler understands that it is an ISR but not
a regular function.

In Keil IDE, we can define the ISR in two ways and in both the cases we need to use the
keyword “__irq”.
// the first way to define ISR
__irq void userISR (void)
{
/////////
}
// or the following way to define the ISR
Void userISR (void) __irq
{
///////
}

15 | Prepared By: U. U. Deshpande


After defining the ISR, now we will setup the interrupt. For example, consider we want to assign
TIMER0 IRQ and the corresponding ISR to Slot 0. For this, we need to follow three steps.

 Enable the TIMER0 IRQ (using VICIntEnable Register)


 Allocate Slot 0 to TIMER0 IRQ (using one of the VICVectCntl0 – 15 Registers)
 Assign the ISR Address (using one of the VICVectAddr0 – 15 Registers)

Based on the above steps, the following assignments must be made to setup the interrupt.
VICIntEnable | = (1<<4);
VICVectCntl0 = 0x20 | 4;
VICVectAddr0 = (unsigned) userISR;

Example program using Interrupts in LPC2148


Now, we will see an example program using interrupts in LPC2148 MCU. We will use the Timer
to generate a delay and a timer interrupt to blink the LEDs.
#include<lpc214x.h>
#define led 0xFFFFFFFF;
int z=0;
/* Function definition for the timer function */
void timer (void)
{
T0CTCR = 0x00;
T0PR = 60000-1;
T0TCR = 0x02;
T0MR0 = 1000-1;
T0MCR = (1<<0) | (1<<1);
}
/* Function definition for the delay function */
void delay (int d)
{
T0TCR=0x02;
T0TCR=0x01;
while (T0TC < d);
T0TCR=0x00;
}
/* ISR for the Interrupt */
__irq void timerISR (void)
{
long int val;
val = T0IR;
if (z==0)
{
IOSET1 = led;
}
else
{
IOCLR1 = led;
}
z=~z;
T0IR = val;
16 | Prepared By: U. U. Deshpande
18 | Predpa By: U. .U aeshpD edn
Programming EINT registers: Examples

1.EXTINT=0x00000001; // clear interrupt flag set by EINT0 interrupt

2.EXTMODE &= 0 << 3; // set level sensitivity to external interrupt EINT3 pin

3.EXTMODE &= 0 << 2;

EXTMODE |= 1 << 2; // set edge sensitivity to external interrupt EINT2 pin

EXTPOLAR &= 0 << 2;

EXTPOLAR |= 1 << 2; // set rising edge sensitivity to EINT2 pin

18 | Prepared By: U. U. Deshpande


Timers
In the GPIO Introduction Tutorial, we have seen an example program to blink a set of LEDs. In
order to show the difference between the LED ON and OFF situations, we have used a simple
delay function. In that delay function, we simply used a “for” loop, where the CPU spend some
time (the amount of time as mentioned in the delay function) so that CPU doesn’t do any other
work.

This method of providing delay in the program is ineffective and affects the performance of the
overall system. Hence, we need to improve this and implement a precise delay function. For this,
we need to use the concept of Timers.

Timers and Counters are often associated with a single module in microcontrollers. The term
Timer / Counter reflects that the responsible module can be configured to count regular clock
pulses, which makes it a Timer or to count an external event, which makes it a counter. The main
and important function of the Timers / Counters in MCUs is to generate precise time delays and
count the external actions.

19 | Prepared By: U. U. Deshpande


Timers
In the GPIO Introduction Tutorial, we have seen an example program to blink a set of LEDs. In
order to show the difference between the LED ON and OFF situations, we have used a simple
delay function. In that delay function, we simply used a “for” loop, where the CPU spend some
time (the amount of time as mentioned in the delay function) so that CPU doesn’t do any other
work.

This method of providing delay in the program is ineffective and affects the performance of the
overall system. Hence, we need to improve this and implement a precise delay function. For this,
we need to use the concept of Timers.

Timers and Counters are often associated with a single module in microcontrollers. The term
Timer / Counter reflects that the responsible module can be configured to count regular clock
pulses, which makes it a Timer or to count an external event, which makes it a counter. The main
and important function of the Timers / Counters in MCUs is to generate precise time delays and
count the external actions.

Timers / Counters in LPC2148:

There are two timer blocks in LPC2148 viz. Timer 0 / Counter 0 and Timer 1 / Counter 1. Both
these timers are 32 – bit timers and both the blocks are identical except their base address is
different.

Either timer blocks can be used as a Timer for triggering an interrupt after certain time or as a
Counter for counting the no. of external events or even demodulate the external PWM signals
(through Capture inputs).

Each timer block is associated with many registers but the two important registers are Timer
Counter and Prescale Register. Both these registers work in coordination with each other.
Prescale Register (PR) defines the resolution of the Timer. When a Timer block in the LPC2148
is reset and Enabled, the Timer Counter (TC) register is set to 0 and is incremented by 1 for
every “PR + 1” clock cycles. When TC reaches the maximum value i.e. 0xFFFF FFFF, the value
gets reset to 0x0000 0000 and starts counting again.

So, if PR is set to 0, the TC increments for every one clock cycle of the peripheral clock (PCLK).
Similarly, if PR is set to 1, the TC increments for every two clock cycles of the peripheral clock.
Hence, the value in the PR register determines when the timer increments or counts.

Before going to discuss the other important registers associated with the Timers, we need to see
about two important registers. Each Timer block has 4 Match Registers and 4 Capture Registers
associated with them. Each of these registers are 32 – bit wide.

The match register consists of a value that is set by the user and this value is continuously
compared with the value in the Timer Counter (TC) register. When the Timer is enables and
every time the value in the TC is incremented, this value is compared with the value in the Match
Register. If the two values are equal, certain actions are automatically triggered. Some of the
actions are Reset the Timer / Counter, stop the Timer or generate an interrupt. All the actions
with respect to Match Registers are controlled using Match Control Register.

19 | Prepared By: U. U. Deshpande


The other register is Capture Register. When an event occurs on a pin that is defined as a Capture
Pin, the value in the Timer Counter (TC) is copied to the Capture Register.

Registers Associated with Timers in LPC2148: Now, we will see a list of most frequently used
registers that are associated with Timer module.

Prescale Register (PR): Prescale Register specifies the maximum value for the Prescale Counter.
When the Prescale Counter (PC) is equal to PR, the TC in incremented on the next clock and
also PC is cleared.

Prescale Counter Register (PC): Prescale Counter increments on every peripheral clock to the
value stored in the PR. When the value in the PC is equal to the value in the PR, PC is reset and
TC is incremented by 1 on the next clock cycle. For example, if PR = 2, then TC is incremented
on every third cycle of the peripheral clock. Hence, PC defines the resolution of the Timer.

Timer Counter Register (TC): The value in the Timer Counter register in incremented when the
value PC reaches its terminal value as set by the PR register. If the PC is reset before reaching its
maximum value, then the TC will count to the maximum possible value i.e. 0xFFFF FFFF (since
it is a 32 – bit register) and resets back to 0x0000 0000.

Timer Control Register (TCR): Timer Control Register is used to control the functions of timer /
counter. It is used to enable / disable or reset the Timer Counter. Only the first two bits of the
TCR must be used for these operations. When the first bit (TSR [0]) is 0, Timer Counter and
Prescale Counter are disabled. When the first bit is 1, the counters are enabled. When the second
bit (TSR [1]) is 1, both the counters (Timer Counter and Prescale Counter) are reset on the next
positive edge of the peripheral clock. They remain reset until the second bit is set to 0.

Count Control Register (CTCR): Count Control Register is used to set either Timer mode or
Counter Mode. If Counter Mode is selected, the counter pin and the edges (rising, falling or
both) can be selected using CTCR. In this tutorial, we are going to use only the Timer Mode and
hence CTCR is set to “0x0”.

Match Control Register (MCR): The Match Control Register is used control the actions to be
performed when the value in the Match Register (MR) matches with the value in the Timer
Counter (TC). Bits 0 to 2 in MCR (i.e. MCR [0], MCR [1] and MCR [2]) are used to control the
actions for MR0 register. Similarly, bits 3 to 5 for MR1, bits 6 to 8 for MR2 and bits 9 to 11 for
MR3 respectively. We will see the function associated with MR0.
 Bit 0: When this bit is 1, an interrupt is triggered when MR0 is equal to TC. When this bit is
0, the interrupts is disabled.
 Bit 1: When this bit is 1, TC is reset when MR0 is equal to TC. When this bit is 0, this
feature is disabled.
 Bit 2: When this bit is 1, the Timer Counter (TC) and Prescale Counter (PC) are stopped
when the value in MR0 is equal to TC. Also, the TC is reset to 0.
Similar actions can be applicable for other Match Register.

Interrupt Register (IR): Interrupt Register consists of flag bits for Match Interrupts and Capture
Interrupts. It contains four bits each for match and capture interrupts. Bits 0 to 3 in the IR register
are for Match Register Interrupts i.e. Bit 0 for MR0 interrupt, Bit 1 for MR1 interrupt etc. Bits 4
to 7 are for Capture Register Interrupts Bit 4 for CR0 interrupt, Bit 5 for CR1 interrupts etc. If an

20 | Prepared By: U. U. Deshpande


interrupt is triggered, then the corresponding bit in the IR register is set to 1. Manually writing a
logic 1 on the bit of the IR register will reset the interrupt.

Configuring Timers:

We have seen the concept of timers, registers associated with timers in LPC2148 and also the
functions related to those registers. The next step is to use the timers in programming. For that
we need to setup and configure the timers. Before configuring the timers, we need to perform
some calculations related to the Prescale Register.
If the CCLK and PCLK are configured at ‘X’ MHz, then the time required for 1 clock cycle is
given by, (1 / X * (10^6)) Seconds.

We will run the system clock (CCLK) and peripheral clock (PCLK) at maximum value i.e. 60
MHz using PLL.

The TC increments for every PR+1 cycles. Hence, if PR = 0, TC increments at every clock cycle
and the time required for TC to increment by 1 is given by
(1 / 60 * (10^6)) seconds = 0.016 µS.
If we set the value of PR as 59999, PR+1 = 60000. So, the time taken for TC to increment by 1 is
given by
(60000 / 60 * (10^6)) = 1 mS.

Now that we have seen some calculations with respect to PR and TC, we will now initialize the
Time block. An important point to remember is that the Timer blocks function with the help of
Peripheral Clock (PCLK). Hence, the PCLK must be initialized before initializing the Timer
block.

In order to initialize the timer, we need to use three registers of the timer block. They are the
Count Control Register (CTCR), Prescale Register (PR) and Timer Control Register (TCR). We
will be initializing the Timer 0 block in this example.

In order to initialize the Timer 0 block, the following steps must be followed.
T0CTCR = 0x0; // Timer Mode is selected.
T0PR = 59999; // PR is set to this value for 1mS delay in incrementing of TC
T0TCR = 0x02; // Reset the Timer
The above steps will initialize the Timer 0 block. Now we will see some commands to get a
delay as per the user requirements in milliseconds. For this, we need to use the Timer Control
Register (TCR) and the Timer Counter register (TC).
In order to get a delay as per the user’s input in milliseconds, we need to use the following steps.
T0TCR = 0x02; // Reset the Timer
T0TCR = 0x01; // Enable the Timer
while (T0TC < time_in_milliseconds); //Wait till the TC reaches the desired delay
T0TCR = 0x00; // Disable the Timer

21 | Prepared By: U. U. Deshpande


Blinking LEDs using LPC2148 and Timers

We have seen a Blinking example in the GPIO tutorial with an ineffective delay function. Now,
we will see another Blinking program using Timers for an efficient delay operation. The
following is the program for blinking LEDs using LPC2148 and Timers.
#include<lpc214x.h>
/* Defining the delay function */
void delay (int);
/* Function definition of delay function */
void delay (int d)
{
T0TCR=0x02;
T0TCR=0x01;
while (T0TC < d);
T0TCR=0x00;
}
int main()
{

PINSEL2=0x00;
/* Configure all pins of PORT 1 as outputs */
IODIR1=0xFFFFFFFF;
/* Initialize the PLL0 and configure it to produce 60 MHz System Clock (CCLK) and Peripheral
Clock (PCLK) */

PLL0CON = 0x01;
PLL0CFG = 0x24;
PLL0FEED = 0xaa;
PLL0FEED = 0x55;
while (!(PLL0STAT & 0x00000400));
PLL0CON = 0x03;
PLL0FEED = 0xaa;
PLL0FEED = 0x55;
VPBDIV = 0x01;
/* Initialize the Timer */
T0CTCR=0x00;
T0PR=59999;
T0TCR=0x02;
while (1)
{
IOSET1=0xFFFFFFFF;
delay(1000);
IOCLR1=0xFFFFFFFF;
delay(1000);
}
}

22 | Prepared By: U. U. Deshpande


LPC2148 PWM Programming

35 | Prepared By: U. U. Deshpande


LPC2148 PWM Programming
PWM or Pulse Width Modulation is a technique that modulates the width of a rectangular pulse
wave in order to get a variation in the average value of the resulting wave. This method is used to
encode the data corresponding to the width of the pulse within the fixed frequency. But the main
application of PWM is to control the power delivered to the loads. The power is controlled by
switching the voltage between the supply and load at an extremely high rate (or depending on the
load).

Although the PWM pin on the LPC214x series of MCUs are mentioned separately, it is based on
the standard Timer block. PWM in LPC2148 are classified in to 2 types: Single Edged PWM
signal and Double Edged PWM signal. In case of Single Edged PWM, the pulse will be always
at the beginning or the ending of the period. Based on the position of the edge, the single edged
PWM is again divided in to Trailing Edge PWM and Leading Edge PWM.

In case of Trailing Edge PWM, the pulse is fixed at the beginning of the period while the
position of the trailing edge is varied. In case of Leading Edge PWM, the pulse is fixed at the
end of the period and the position of the leading edge is varied.

Coming to the Double Edge PWM signal, the pulse can be placed anywhere in the period and
either the leading edge or the trailing edge can be modulated.

LPC2148 has a six channel PWM block based on seven match registers that is capable of
generating six channels of Single Edged PWM signal or three channel Double Edged PWM
signal. The following pins on the LPC2148 are used to generate PWM.

Output : PWM1 PWM2 PWM3 PWM4 PWM5 PWM6


Pin Name : P0.0 P0.7 P0.1 P0.8 P0.21 P0.9

When we are talking about PWM outputs, what we actually mean is the output of the PWM
Match Registers and 6 of these match registers are pinned on the LPC2148. So, PWM1 – 6
outputs are associated with PWM Match Registers 1 – 6. The PWM Match Register 0 is not
pinned to LPC2148 but is used to control the Duty Cycle or period of the PWM output.
Note: In order to select the PWM function of the Pin, we need to set the PINSEL registers. PWM
1 to 4 and PWM 6 are set using PINSEL0 register and PWM 5 is set using PINSEL1.

35 | Prepared By: U. U. Deshpande


Understanding PWM in LPC2148

Let us consider period of the PWM signal is 8 milliseconds. With the help suitable prescale
value, the PWM Timer Counter (PWM TC) is set to increment every 1 millisecond. Hence, the
value in the PWM Match Register 0 i.e. PWMMR0 must be 8.

The next step is to reset the value in PWM TC whenever it reaches the value in PWMMR0 and
begin a new period.

Let us assume we want to generate two PWM outputs with individual pulse widths of 3
milliseconds and 5 milliseconds. For this purpose, let us use PWM1 and PWM2 i.e. PWMMR1
and PWMMR2. As per the requirement, we need to assign PWMMR1 as 3 and PWMMR2 as 5
i.e. PWMMR1 = 3 and PWMMR2 = 5.

On the start of a new period, the PWM1 and PWM2 pins will be set to HIGH by default. When
the value in the PWM TC matches with the value in PWMMR1 or PWMMR2, the corresponding
pins will be set to LOW. The pins will remain LOW until the next period starts. Hence, the
output of the PWM pins is a single edge PWM.

Rules for Single Edge PWM Output

NXP Semiconductors (the manufacturers of the LPC series of MCUs) laid out some rules
regarding the single edge PWMs in their official user manual for the LPC214x series of MCUs.

 Unless the corresponding Match Register value is ‘0’, the outputs of all the single edge
PWM pins will be HIGH at the beginning of the period.
 When the PWM TC reaches the Match Register value, corresponding PWM output will
become LOW. In case the value in the PWM Match Register is higher than the period of the
PWM, then the PWM will be continuously HIGH.

There are also rules for Double Edge PWM Output mentioned in the user manual.

PWM Related Registers in LPC2148

Now we will see a list of register that are associated with PWM in LPC2148.

PWM Timer Control Register (PWMTCR): PWM Timer Control Register is used to control the
PWM Timer Counter. This Timer Counter is specific to the PWM block. Bit 0 in the PWMTCR
register is used to enable or disable the counter in PWM block. When this bit is 1, the PWM TC
and PWM Prescale Counter are enabled. When this bit is 0, both are disabled. Bit 1 is used to
reset the PWM TC and PWM Prescale Counter. Bit 3 is used to enable or disable the PWM
Mode.

PWM Prescale Register (PWMPR): PWM Prescale Register is used to set the resolution of the
PWM outputs. The PWM TC will increment for every PWMPR + 1 PCLK cycles.

PWM Match Registers (PWMMR0 – PWMMR6): Each PWM Match Register is associated with
each PWM pin i.e. PWM 1 to PWM 6 are associated with PWMMR1 to PWMMR6 respectively.
The values in the PWM Match Register are compared with the value in PWM TC.
36 | Prepared By: U. U. Deshpande
PWM Match Control Register (PWMMCR): The PWM Match Control Register is used to
control the operations that can be done when the value in the PWM Match registers and PWM
TC register are same. Three bits are associated with each Match Register i.e. Bit 0, Bit 1 and Bit
2 for PWMMR0, Bit 3, Bit 4 and Bit 5 for PWMMR1, etc. If we consider PWMMR0, the Bit 0
in PWMMCR is used to enable an interrupt, Bit 1 is used to reset the PWM TC and Bit 2 is used
to stop the PWM TC and PWM PC.

PWM Interrupt Register (PWMIR): PWM Interrupt Register is used to identify the interrupts
based on PWM Match Registers. There are 7 bits in PWMIR corresponding to 7 PWM Match
Register Interrupts. When an interrupt occurs, the corresponding bit in the PWMIR register is set
to HIGH. If the bit is manually set to HIGH, the interrupt is reset.

Bit in PWMIR Corresponding Match Register


Bit 0 PWMMR0
Bit 1 PWMMR1
Bit 2 PWMMR2
Bit 3 PWMMR3
Bit 8 PWMMR4
Bit 9 PWMMR5
Bit 10 PWMMR6

PWM Latch Enable Register (PWMLER): When PWM Match Registers are used to generate
PWM signals, the PWM Latch Enable Register is used to control its update. When the value of
the PWM Match Registers are updated when the PWM is active, the values will be stored in a
shadow register. When an event occurs on the PWMMR0 register, the values will be transferred
to the Match Registers from the shadow register only if the corresponding bit in the PWMLER is
set to 1.
PWM Control Register (PWMPCR): PWM Control Register is used to enable or disable the
PWM outputs and also select the mode of PWM i.e. either single edge or double edge. Bit 2 to
Bit 6 in the PWMPCR register are used to set the PWM output as either single edge or double
edge for PWM2 to PWM6. Bit 9 to Bit 14 are used to enable or disable the PWM1 to PWM6
outputs respectively.

Configuring PWM in LPC2148

From the list of PWM related registers we have seen above, it is clear that configuring PWM will
be similar to that of Timers in LPC2148. The additional things we need to do are enabling the
PWM outputs and selecting the PWM functions of the corresponding pins. Before going in to
configuring the PWM we need to calculate the resolution of the PWM using the Prescale value.

PWM block derives its clock from the Peripheral Clock (PCLK) which is clocked at 60 MHz.
So, to get a time required for PCLK to run for ‘X’ clock cycles at 60 MHz is
X / (60 * 10^6).

37 | Prepared By: U. U. Deshpande


If the Prescale is considered, then X = PR + 1. So, when we consider the Prescale value to be 59,
then we get a delay of
Delay = (59 + 1) / (60 * 10^6) = 1 microsecond (1 µS).
Similarly, if we set the PR to 59999, then we get a delay of
Delay = (59999 + 1) / (60 * 10^6) = 1 millisecond (1 mS).
Now that we have seen the Prescale calculations for PWM, next we will see the steps that we
need to follow in order to in initialize the PWMs.

 First thing we need to do is set the PWM function of the corresponding pins using PINSEL0
and PINSEL1 registers.
 Next, we need to select the mode of the PWM i.e. single edge or double edge using
PWMPCR register. Single Edge PWM is set by default.
 The resolution of the PWM, which is defined by the Prescale value, is set to the Prescale
Register.
 The cycle rate of the PWM signal i.e. the period of the PWM signal is set using the
PWMMR0 register.
 The pulse widths of the PWM outputs are set using the match registers i.e. PWMMR1
through PWMMR6.
 The operations like reset of the PWM TC, interrupts etc. are set for PWMMR0 match using
the PWMMCR register.
 The next important step is to set the Latch Enable bits to the corresponding Match Registers
using PWMLER register.
 Next, we need to enable the PWM outputs. In order to do this, we need to use the PWMPCR
register.
 Similarly, we need to reset the PWM Timers. To reset the Timers, we need to make use of
PWMTCR register.
 And the last thing we need to do is to enable the PWM Timer Counters and the PWM Mode.
For this, we have to use the PWMTCR register again.

Example Program for PWM in LPC2148


We will now see a real time example of PWM generation in LPC2148. In this example, we will
control the power delivered to an LED i.e. the dimming operation of the LED using PWM
Function. For this we assume that an LED is connected to P0.21 which provides the PWM5
output. Also, four push buttons are connected to P0.15, P0.16, P1.16 and P1.17 pins as per the
development board we are using for the demonstration.
#include<lpc214x.h>
int main()
{
PINSEL0=0x00000000; // P0.0 to P0.15 pins of PORT0 as GPIO
PINSEL1=0x00000400; // P0.21 Pin of PORT0 as PWM
PINSEL2=0x00000000; // P1.16 to P1.31 pins of PORT1 as GPIO
/*Configure the PLL block and set the CCLK and PCLK at 60 MHz */
PLL0CON=0x01;
PLL0CFG=0x24;
PLL0FEED=0xaa;
PLL0FEED=0x55;
while (! (PLL0STAT & 0x00000400));
PLL0CON=0x03;
38 | Prepared By: U. U. Deshpande
PLL0FEED=0xaa;
PLL0FEED=0x55;
VPBDIV=0x01;
/* Setup and initialize the PWM block */
PWMPCR=0x00; // Single Edge PWM Mode
PWMPR=60000-1; // Resolution of PWM is set at 1 mS
PWMMR0=10; // Period of PWM is 10 mS
PWMMR5=1; // Pulse width of PWM5 is 1 mS
PWMMCR= (1<<1); // PWMTC is reset on match with PWMMR0
PWMLER= (1<<5)| (1<<0); // Update Match Registers PWMMR0 and PWMMR5
PWMPCR= (1<<13); // Enable PWM5 output
PWMTCR= (1<<1); // Reset PWM TC and PWM PR
PWMTCR= (1<<0)| (1<<3); // Enable PWM Timer Counters and PWM Mode
while (1)
{
if (! ((IO0PIN) & (1<<15))) // Check for P0.15
{
PWMMR5 = 1;
PWMLER = (1<<5); //Update Latch Enable bit for PWMMR5
}
else if ( ! ((IO0PIN) & (1<<16))) // Check P0.16
{
PWMMR5 = 2;
PWMLER = (1<<5);
}
else if (! ((IO1PIN) & (1<<16)) ) // Check for P1.16
{
PWMMR5 = 4;
PWMLER = (1<<5);
}
else if (! ((IO1PIN) & (1<<17))) // Check for P1.17
{
PWMMR5 = 8;
PWMLER = (1<<5);
}
}
//return 0;
}

39 | Prepared By: U. U. Deshpande

You might also like