Unit 3 Timer
Unit 3 Timer
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.
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.
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.
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
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).
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.
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.
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
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.
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.
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.
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
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
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’.
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.
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.
SPI1/SS
IRQ USB AD1 BOD I2C1 AD0 EINT3 EINT2 EINT1 EINT0 RTC PLL
P
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.
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.
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
{
///////
}
Based on the above steps, the following assignments must be made to setup the interrupt.
VICIntEnable | = (1<<4);
VICVectCntl0 = 0x20 | 4;
VICVectAddr0 = (unsigned) userISR;
2.EXTMODE &= 0 << 3; // set level sensitivity to external interrupt EINT3 pin
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.
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.
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.
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
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
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);
}
}
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.
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.
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.
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.
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.
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.
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).
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.