Introduction
Using delays in a software code is usual to embedded programmers. A normal delay function might be used to create a period of no operation through a for loop iterating for a few 1000 cycles. But these types of delays need not be accurate and fundamentally, it is not a good programming practice. So, TIMER/COUNTER is a software designed to count the time interval between events. It counts the cycle of the peripheral clock or an externally-supplied clock.
Features
- The LPC 1768 has 4 general purpose timers. (TIMER 0, TIMER 1, TIMER 2, TIMER 3)
- 32-bit Timer/Counter
- 32-bit prescaler
- Four 32 bit match registers
- Four external outputs corresponding to match registers
Configuration
- As usual, the first configuration setting is enabling the power supply of the peripheral, in this case, PCTIMx where x is 0,1,2, or 3.
- Next, the peripheral clock must be set in the PCLKSEL0 register to set the appropriate bits of the respective timer.
- Timer pins have to be selected through the PINSEL register…
- Finally, the necessary match registers, values, and the eventual event must be configured based on the necessary results.
Firmware
- DEFINITIONS: These are the definitions that will be used in this code.
#define Power_Control_Reg LPC_SC->PCONP #define Match_Control_Reg LPC_TIM0->MCR #define Peripheral_Clk0 LPC_SC->PCLKSEL0 #define Peripheral_Clk1 LPC_SC->PCLKSEL1 #define Prescalar_Reg LPC_TIM0->PR #define Timer0_Match_Reg LPC_TIM0->MR0 #define Timer0_Timer_Counter LPC_TIM0->TCR #define Interrupt_Reg LPC_TIM0->IR #define MatchReg0_Int 0 #define MatchReg0_Rst 1 #define Timer0_Power 1 #define Timer1_Power 2 #define Timer2_Power 22 #define Timer3_Power 23 #define Timer0_Peripheral 2 #define Timer1_Peripheral 4 #define Timer2_Peripheral 12 #define Timer3_Peripheral 14 #define Timer_Counter_Enable 0 #define BlinkDir LPC_GPIO2->FIODIR #define BlinkPin LPC_GPIO2->FIOPIN #define Led 0
- POWER: We will be using Timer 0 in our tutorial. Since Timer 0/1 have reset value as 1, the peripheral is already enabled. But if you are using Timer 2/3, this step is important as they have 0 as the reset value.
Power_Control_Reg |= (1<<Timer0_Power); Match_Control_Reg = (1<<MatchReg0_Int) | (1<<MatchReg0_Rst);
- PERIPHERAL CLOCK & PRESCALER: The PCLKSEL0 register contains the peripheral clock selection for timers 0 and 1 and PCLKSEL1 register contains the peripheral clock selection for timers 2 and 3. As in most case, the reset value is 00.
The PCLK is necessary as it gives the number of clock cycles required to increment the timer counter by 1.
And the required value is entered in the prescaler register.PreScale = pclk/ReqCntsPerSec; Prescalar_Reg = PreScale - 1;
- MATCH CONTROL REGISTER: The match register will be configured in such a way that it resets on every match with the timer counter as well as an interrupt occurs on the match. We are going to generate a 1-second delay, hence the required value has been entered in the MR0 register.
Match_Control_Reg = (1<<MatchReg0_Int) | (1<<MatchReg0_Rst); Timer0_Match_Reg = 1000000; // 1 sec delay
- NESTED VECTORED INTERRUPT CONTROL: This calls the interrupt routine. Inside the interrupt handler, bit 0 of the timer 0 interrupt register is set when a match occurs. This value has to be cleared by writing logic 1 to it. And then the LED toggling is done.
void TIMER0_IRQHandler(void) { uint8_t interrupt_bit; interrupt_bit = Interrupt_Reg; // When MR0 match occurs, flag is set. Bit 0 of T0 interrupt reg Interrupt_Reg = interrupt_bit; // Writing logic 1 clears the flag BlinkPin ^= (1<<Led); // Toggle the LED }
Summary
The same logic can be applied to generate different types of delays based on your particular application. Creating a delay that is calculated based on the peripheral clocks is always a good coding practice. The sample code for this tutorial is available in the Code Library under the section ARM.