Таймер и Обработка прерываний в LPC210x

Posted by ViRuZzz

Проковырялся с прерываниями на LPC2103 больше недели (периодически это забрасывая и потом снова к этому возвращаясь). У меня прерывания либо выполнялось только 1 раз, после него только более высокоприоритетное, либо прерывание “зацикливалось”.
Компилирую я естественно GCC, ибо денег на коммерческие среды разработки и компиляторы мне жалко.
Оказалось что чтобы прерывание завершить нужно сбросить адрес прерывания в VIC (VICVectAddr=0) и сбросить прерывание в той части контроллера которая его вызвала (например в таймере).
Вот пример для таймера и EINT
void __attribute__((interrupt("IRQ"))) TMR_ISR( void ) {
  IOSET = (1<<LED0PIN); // Радостно зажигаем светодиод
  T1IR = 0x00000003; //Сбрасываем match 0 и match 1 (у меня на оба прерывания один обработчик)
  VICVectAddr = 0; //Сбрасываем interrupt из VIC
}
void __attribute__((interrupt("IRQ"))) EINT0_ISR( void ) {
  IOSET = (1<<LED1PIN); //светодиод
  EXTINT=0x00000001; // EINT0 сбросить
  VICVectAddr = 0; // из VIC тоже сбросить
}

А повесить прерывание на EINT0 вот так:

PINSEL1 |= (1<<0); // Пишем 1 в 0й разряд
PINSEL1 &= ~(1<<1); // и 0 в 1й, чтобы сказать что эта нога камня будет у нас EINT0
EXTINT |= (1<<0); // Разрешаем генерить прерывания
VICIntSelect &= ~(1<<VIC_EINT0); // Мы записываем 0 в соотвествующий бит VIC чтобы сказать что это IRQ а не FIQ
VICIntEnable |= (1<<VIC_EINT0); // Разрешаем прерывание
VICVectCntl3 |= VIC_ENABLE | VIC_EINT0; // Регистрируем в 3й вектор наше прерывание EINT0
VICVectAddr3 = (uint32_t)EINT0_ISR; // Указываем какая функция будет его обрабатывать.
T1TCR = TCR_RESET; // выключаем и сбрасываем таймер
T1PR=500; // выставляем прескалер
T1TC=0; // Сбрасываем таймер в 0 (наверное не обязательно)
T1MR0=0x0000ffff; // как только досчитает до 0xffff сработает match register0
T1MCR|=(1< <0); // и вызовит прерывание
//T1MCR|=(1<<2); // а еще он может сброс сделать
T1MR1=0x0002ffff; // А когда досчитает до 2ffff сработает MR1
T1MCR|=(1<<3); // И тоже вызовит прерывание
T1TCR = TCR_ENABLE; // включаем таймер
VICIntSelect &= ~(1<<VIC_TIMER1);
VICIntEnable |= (1<<VIC_TIMER1);
VICVectCntl4 |= VIC_ENABLE | VIC_TIMER1;
VICVectAddr4 = (uint32_t)TMR_ISR;

вот так прерывания будут срабатывать и корректно завершаться :)

One Response to “Таймер и Обработка прерываний в LPC210x”

  1. Хм

Leave a Reply

You must be logged in to post a comment.