Reputation: 335
I have LPC1769 LPCXpresso and LPC-Link 2 for debugging. My development environment is IAR.
I wanted to experience a simple LED blinking using Timer. There are many sample codes on the net. So, I picked one of the samples made for MCB1700 board. I have also read some here and there how timer works with LPC's.
The code compiles and I downloaded the program to the device (LPC1769). I was assuming the LED should blink when the timer calls the handler by the given interval.
But, the program never hits TIMER0_IRQHandler at all.
Here is the complete code in my main.c file:
#include <lpc17xx.h>
void TIMER0_IRQHandler(void);
int main(void)
{
// (1) Timer 0 configuration (see page 490 of user manual)
LPC_SC->PCONP |= 1 << 1; // Power up Timer 0 (see page 63 of user manual)
LPC_SC->PCLKSEL0 |= 1 << 2; // Clock for timer = CCLK, i.e., CPU Clock (page 56 user manual)
// MR0 is "Match Register 0". MR0 can be enabled through the MCR to reset
// the Timer/Counter (TC), stop both the TC and PC, and/or generate an interrupt
// every time MR0 matches the TC. (see page 492 and 496 of user manual)
LPC_TIM0->MR0 = 500; //Toggle Time in mS
//LPC_TIM0->MR0 = 1 << 23; // Give a value suitable for the LED blinking
// frequency based on the clock frequency
// MCR is "Match Control Register". The MCR is used to control if an
// interrupt is generated and if the TC is reset when a Match occurs.
// (see page 492 and 496 of user manual)
LPC_TIM0->MCR |= 1 << 0; // Interrupt on Match 0 compare
LPC_TIM0->MCR |= 1 << 1; // Reset timer on Match 0
// TCR is "Timer Control Register". The TCR is used to control the Timer
// Counter functions. The Timer Counter can be disabled or reset
// through the TCR. (see page 492 and 494 of user manual)
LPC_TIM0->TCR |= 1 << 1; // Manually Reset Timer 0 (forced);
LPC_TIM0->TCR &= ~(1 << 1); // Stop resetting the timer
// (2) Enable timer interrupt;
// TIMER0_IRQn is 1, see lpc17xx.h and page 73 of user manual
NVIC_EnableIRQ(TIMER0_IRQn); // see core_cm3.h header file
// (3) Some more one-time set-up's;
LPC_TIM0->TCR |= 1 << 0; // Start timer (see page 492 and 494 of user manual)
LPC_SC->PCONP |= ( 1 << 15 ); // Power up GPIO (see lab1)
LPC_GPIO1->FIODIR |= 1 << 29; // Put P1.29 into output mode. LED is connected to P1.29
// (4) infinite loop;
while (1) // Why do we need this?
{
//LPC_GPIO1->FIOPIN ^= 1 << 29; // Toggle the LED (see lab1)
}
return 0;
}
// Here, we describe what should be done when the interrupt on Timer 0 is handled;
// We do that by writing this function, whose address is “recorded” in the vector table
// from file startup_LPC17xx.s under the name TIMER0_IRQHandler;
void TIMER0_IRQHandler(void)
{
// IR is "Interrupt Register". The IR can be written to clear interrupts. The IR
// can be read to identify which of eight possible interrupt sources are
// pending. (see page 492 and 493 of user manual)
if ( (LPC_TIM0->IR & 0x01) == 0x01 ) // if MR0 interrupt (this is a sanity check);
{
LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag (see page 492 and 493 of user manual)
LPC_GPIO1->FIOPIN ^= 1 << 29; // Toggle the LED (see lab1)
}
}
Any pointer would be greatly appreciated.
[EDIT]
For future reference for whom has the similar question, here is my working code;
I have re-written with knowledge I gathered from here and there.
Now it works, all handlers are triggered. This time I wanted to test with multiple Timers. Here is the implementation with two Timer-IRQ
's and SysTick
.
#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);
static int data_main = 0;
static int data_systick = 0;
void Delay(uint32_t Dly)
{
for(volatile uint32_t j = Dly; j; j--) { }
}
void SysTick_Handler(void)
{
data_systick += 10;
}
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 */
SysTick_Config(900000);
while(1)
{
data_main++;
}
}
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;
}
Upvotes: 0
Views: 1054
Reputation: 11
I ran your code and I can tell you that the TIMER0_IRQHandler is indeed executing, at least for me. To prove this try running the IAR IDE debugger and set a "break point" at the line:
void TIMER0_IRQHandler(void)
The program will pause at this function call every time it enters it.
I don't have too much experience with the lower level function calls of the lpc1769 but I can see that the problem in your code lies here:
LPC_TIM0->MR0 = 500; //Toggle Time in mS
//LPC_TIM0->MR0 = 1 << 23; // Give a value suitable for the LED blinking
There is no prescale value for the match register MR0 so instead of executing every 500 mS, it is executing every 500 uS. This is similar to creating a PWM signal which will make the LED blink so fast it is invisible to the naked eye. You might try learning more about setting a prescale value with LPC_TIM0->PR to increment the timer/counter at a value higher than 1uS. Without using a prescale I was able to blink my LED every 1 second by setting:
LPC_TIM0->MR0 = 100000000;
Also make sure you have a resistor in your LED circuit so you don't fry it. Make sure that the output pin P1.29 which you have set is wired to the right spot on the board (PAD 12?): LPC Xpresso Pinout
Hope this helps!
Upvotes: 1