In this tutorial, we are going to discuss the Timer module of LPC2148 .
First, we will see how to configure the Timer0 and Timer1 registers to generate a delay of 100ms and 500ms respectively. At the end, we will see how to use the ExploreEmdedded Timer library.
Contents
[hide]LPC2148 Timer Module
LPC1768 has four 32-bit independent timers (Timer0-Timer3). Each timer has a 32-bit pre-scalar to generate wide range of delays.
Each timer has 4 match registers with which 4 different delays can be generated using a single timer.
LPC7168 Timer Registers
The below table shows the registers associated with LPC1768 Timer module.
Register | Description |
---|---|
IR | Interrupt Register: The IR can be read to identify which of 6(4-match, 2-Capture) possible interrupt sources are pending. Writing Logic-1 will clear the corresponding interrupt. |
TCR | Timer Control Register: The TCR is used to control the Timer Counter functions(enable/disable/reset). |
TC | Timer Counter: The 32-bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. |
PR | Prescaler Register: This is used to specify the Prescaler value for incrementing the TC. |
PC | Prescale Counter: The 32-bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented. |
MCR | Match Control Register: The MCR is used to control the resetting of TC and generating of interrupt whenever a Match occurs. |
MR0-MR3 | Match Registers: The Match register values are continuously compared to the Timer Counter value. When the two values are equal, actions can be triggered automatically. The action possibilities are to generate an interrupt, reset the Timer Counter, or stop the timer. Actions are controlled by the settings in the MCR register. |
Register Configuration
TCR | ||
---|---|---|
31:2 | 1 | 0 |
Reserved | Counter Reset | Counter Enable |
Bit 0 – Counter Enable
This bit is used to Enable or Disable the Timer Counter and Prescalar Counter
0- Disable the Counters
1- Enable the Counter incrementing.
Bit 1 – Counter reset
This bit is used to clear the Timer counter and PWM Prescalar Counter values.
0- Do not Clear.
1- The Timer Counter and the Prescaler Counter are synchronously reset on the next positive edge of PCLK.
MCR | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
31:21 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Reserved | MR3S | MR3R | MR3I | MR2S | MR2R | MR2I | MR1S | MR1R | MR1I | MR0S | MR0R | MR0I |
MRxI
This bit is used to Enable or Disable the Timer interrupts when the TC matches MRx (x:0-3)
0- Disable the Timer Match interrupt
1- Enable the Timer Match interrupt.
MRxR
This bit is used to Reset TC whenever it Matches MRx(x:0-3)
0- Do not Clear.
1- Reset TC counter value whenever it matches MRx.
MRxS
This bit is used to Stop TC and PC whenever the TC matches MRx(x:0-3).
0- Disable the Timer stop on match feature
1- Enable the Timer Stop feature. This will stop the Timer whenever the TC reaches the Match register value.
Prescalar Calculation
Timer delay generated by the LPC1768 depends on the input clock and the pre-scalar values. The required pre-scalar value can be determined by the pclk (peripheral clock). PCLKSEL0 and PCLKSEL1 register have the PCLK info for all the 4 timers.
Timer | PCLKSELx | Bits | Symbol | Description |
Timer0 | PCLKSEL0 | 3-2 | PCLK_TIMER0 | Peripheral clock selection for TIMER0. |
Timer1 | PCLKSEL0 | 5-4 | PCLK_TIMER1 | Peripheral clock selection for TIMER1. |
Timer2 | PCLKSEL1 | 13-12 | PCLK_TIMER2 | Peripheral clock selection for TIMER2. |
Timer3 | PCLKSEL1 | 15-14 | PCLK_TIMER3 | Peripheral clock selection for TIMER3. |
Getting the PCLK value.
Using the 2-bit information from PCLKSELx registers the pclk can be determined as below..
PCLKSELx bits | PCLK |
0 | SystemCoreClock/4 |
1 | SystemCoreClock |
2 | SystemCoreClock/2 |
3 | SystemCoreClock/8 |
Calculating the Pre-scalar value.
After getting the pclk value the prescalar count for 1us delay can be calculated as below.
unsigned int getPrescalarForUs(uint8_t timerPclkBit) | |
{ | |
unsigned int pclk,prescalarForUs; | |
pclk = (LPC_SC->PCLKSEL0 >> timerPclkBit) & 0x03; /* get the pclk info for required timer */ | |
switch ( pclk ) /* Decode the bits to determine the pclk*/ | |
{ | |
case 0x00: | |
pclk = SystemCoreClock/4; | |
break; | |
case 0x01: | |
pclk = SystemCoreClock; | |
break; | |
case 0x02: | |
pclk = SystemCoreClock/2; | |
break; | |
case 0x03: | |
pclk = SystemCoreClock/8; | |
break; | |
} | |
prescalarForUs =pclk/1000000 - 1; /* Prescalar for 1us (1000000Counts/sec) */ | |
return prescalarForUs; | |
} |
Timer Working
Steps to Configure Timer
- Power On the Timer module by setting the appropriate bits in PCONP register.
- Configure MCR to reset the TC and generate the interrupt whenever it matches MRx.
- Set the pre-scalar value for 1us.
- Update the MRx register with required delay in micro secs.
- Configure TCR to enable the Counter for incrementing the TC.
- Enable the required timer interrupt.
- Configure the GPIO pins as output for blinking the LEDs.
- Toggle the LEDs in ISR whenever the interrupt is generated.
Example
Program to demonstrates the led blinking with 100ms and 500ms delay using the timer interrupts
#include "LPC17xx.h" | |
#define SBIT_TIMER0 1 | |
#define SBIT_TIMER1 2 | |
#define SBIT_MR0I 0 | |
#define SBIT_MR0R 1 | |
#define SBIT_CNTEN 0 | |
#define PCLK_TIMER0 2 | |
#define PCLK_TIMER1 4 | |
#define LED1 0 // P2_0 | |
#define LED2 1 // P2_1 | |
#define MiliToMicroSec(x) (x*1000) /* ms is multiplied by 1000 to get us*/ | |
extern unsigned int SystemCoreClock; | |
unsigned int getPrescalarForUs(uint8_t timerPclkBit); | |
int main (void) | |
{ | |
SystemInit(); | |
LPC_SC->PCONP |= (1<<SBIT_TIMER0) | (1<<SBIT_TIMER1); /* Power ON Timer0,1 */ | |
LPC_TIM0->MCR = (1<<SBIT_MR0I) | (1<<SBIT_MR0R); /* Clear TC on MR0 match and Generate Interrupt*/ | |
LPC_TIM0->PR = getPrescalarForUs(PCLK_TIMER0); /* Prescalar for 1us */ | |
LPC_TIM0->MR0 = MiliToMicroSec(100); /* Load timer value to generate 100ms delay*/ | |
LPC_TIM0->TCR = (1 <<SBIT_CNTEN); /* Start timer by setting the Counter Enable*/ | |
NVIC_EnableIRQ(TIMER0_IRQn); /* Enable Timer0 Interrupt */ | |
LPC_TIM1->MCR = (1<<SBIT_MR0I) | (1<<SBIT_MR0R); /* Clear TC on MR0 match and Generate Interrupt*/ | |
LPC_TIM1->PR = getPrescalarForUs(PCLK_TIMER1); /* Prescalar for 1us */ | |
LPC_TIM1->MR0 = MiliToMicroSec(500); /* Load timer value to generate 500ms delay*/ | |
LPC_TIM1->TCR = (1 <<SBIT_CNTEN); /* Start timer by setting the Counter Enable*/ | |
NVIC_EnableIRQ(TIMER1_IRQn); /* Enable Timer1 Interrupt */ | |
LPC_GPIO2->FIODIR = (1<<LED1) | (1<<LED2); /* Configure the LED pins(P2_0,P2_1) as outputs */ | |
while(1) | |
{ | |
//do nothing | |
} | |
} | |
void TIMER0_IRQHandler(void) | |
{ | |
unsigned int isrMask; | |
isrMask = LPC_TIM0->IR; | |
LPC_TIM0->IR = isrMask; /* Clear the Interrupt Bit */ | |
LPC_GPIO2->FIOPIN ^= (1<<LED1); /* Toggle the LED1 (P2_0) */ | |
} | |
void TIMER1_IRQHandler(void) | |
{ | |
unsigned int isrMask; | |
isrMask = LPC_TIM1->IR; | |
LPC_TIM1->IR = isrMask; /* Clear the Interrupt Bit */ | |
LPC_GPIO2->FIOPIN ^= (1<<LED2); /* Toggle the LED2 (P2_1) */ | |
} | |
unsigned int getPrescalarForUs(uint8_t timerPclkBit) | |
{ | |
unsigned int pclk,prescalarForUs; | |
pclk = (LPC_SC->PCLKSEL0 >> timerPclkBit) & 0x03; /* get the pclk info for required timer */ | |
switch ( pclk ) /* Decode the bits to determine the pclk*/ | |
{ | |
case 0x00: | |
pclk = SystemCoreClock/4; | |
break; | |
case 0x01: | |
pclk = SystemCoreClock; | |
break; | |
case 0x02: | |
pclk = SystemCoreClock/2; | |
break; | |
case 0x03: | |
pclk = SystemCoreClock/8; | |
break; | |
default: | |
pclk = SystemCoreClock/4; | |
break; | |
} | |
prescalarForUs =pclk/1000000 - 1; /* Prescalar for 1us (1000000Counts/sec) */ | |
return prescalarForUs; | |
} |
Using ExploreEmbedded Libraries
In the above tutorial we just discussed how to configure and use the Timer module of LPC1768 to generate 100ms and 500ms delay
Once you know the internals of LPC7168 Timers, you can directly use the ExploreEmbedded libraries to generate the required Delays.
The below sample code shows how to use the ExploreEmbedded Timer library.
#include <lpc17xx.h> | |
#include "stdutils.h" | |
#include "gpio.h" | |
#include "timer.h" | |
#define LED1 P2_0 | |
#define LED2 P2_1 | |
void myTimerIsr_0(void) | |
{ | |
GPIO_PinToggle(LED1); /* Toggle the LED1 (P2_0) */ | |
} | |
void myTimerIsr_1(void) | |
{ | |
GPIO_PinToggle(LED2); /* Toggle the LED2 (P2_1) */ | |
} | |
int main (void) | |
{ | |
SystemInit(); | |
GPIO_PinDirection(LED1,OUTPUT); /* Configure the pins as Output to blink the Leds*/ | |
GPIO_PinDirection(LED2,OUTPUT); | |
TIMER_Init(0,100000); /* Configure timer0 to generate 100ms(100000us) delay*/ | |
TIMER_Init(1,500000); /* Configure timer1 to generate 500ms(500000us) delay*/ | |
TIMER_AttachInterrupt(0,myTimerIsr_0); /* myTimerIsr_0 will be called by TIMER0_IRQn */ | |
TIMER_AttachInterrupt(1,myTimerIsr_1); /* myTimerIsr_1 will be called by TIMER1_IRQn */ | |
TIMER_Start(0); /* Start the Timers */ | |
TIMER_Start(1); | |
while(1) | |
{ | |
//do nothing | |
} | |
} |
Timer Delay measured using CRO.
Downloads
Download the complete project folder from the below link:
Have an opinion, suggestion , question or feedback about the article let it out here!