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.
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 ) is 0, Timer Counter and Prescale Counter are disabled. When the first bit is 1, the counters are enabled. When the second bit (TSR ) 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 , MCR  and MCR ) 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 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.
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.
/* Defining the delay function */
void delay (int);
/* Function definition of delay function */
void delay (int d)
while (T0TC < d);
/* Configure all pins of PORT 1 as outputs */
/* 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 */