Прерывание таймера никогда не достигает TIMER0_IRQHandler с LPC1769 LPCXpresso - PullRequest
0 голосов
/ 05 марта 2019

У меня есть LPC1769 LPCXpresso и LPC-Link 2 для отладки. Моя среда разработки - IAR.

Я хотел испытать простое мигание светодиода с помощью таймера. В сети много примеров кодов. Итак, я выбрал один из образцов, сделанных для платы MCB1700. Я также кое-где прочитал, как таймер работает с LPC.

Код компилируется, и я загрузил программу на устройство (LPC1769). Я предполагал, что светодиод должен мигать, когда таймер вызывает обработчик на заданный интервал.

Но программа никогда не запускает TIMER0_IRQHandler.

Вот полный код в моем файле main.c:

#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)
  }
}

Любой указатель будет принят с благодарностью.

[EDIT]

Для дальнейшего использования у кого есть аналогичный вопрос, вот мой рабочий код;

Я переписал со знанием, которое я собрал отсюда и там. Теперь это работает, все обработчики запущены. На этот раз я хотел проверить с несколькими таймерами. Вот реализация с двумя Timer-IRQ и 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;
}

1 Ответ

1 голос
/ 06 марта 2019

Я запустил ваш код и могу сказать, что TIMER0_IRQHandler действительно выполняется, по крайней мере, для меня. Чтобы доказать это, попробуйте запустить отладчик IAR IDE и установить «точку останова» в строке:

void TIMER0_IRQHandler(void)

Программа будет приостанавливать этот вызов функции каждый раз, когда входит в нее.

У меня не так много опыта с вызовами функций более низкого уровня lpc1769, но я вижу, что проблема в вашем коде лежит здесь:

LPC_TIM0->MR0 = 500; //Toggle Time in mS
//LPC_TIM0->MR0 = 1 << 23; // Give a value suitable for the LED blinking

Для регистра совпадения MR0 нет значения перед масштабированием, поэтому вместо выполнения каждые 500 мсек он выполняется каждые 500 мсек. Это похоже на создание сигнала ШИМ, который заставит светодиод мигать так быстро, что он будет невидим невооруженным глазом. Вы можете попытаться узнать больше о настройке значения до шкалы с помощью LPC_TIM0-> PR, чтобы увеличить таймер / счетчик на значение, превышающее 1 мкс. Без использования предварительной шкалы я мог мигать своим светодиодом каждую секунду, установив:

LPC_TIM0->MR0 = 100000000;

Также убедитесь, что в вашей светодиодной цепи есть резистор, чтобы не жарить его. Убедитесь, что выходной контакт P1.29, который вы установили, подключен к правильному месту на плате (PAD 12?): LPC Xpresso Pinout

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...