Прерывания Arduino

Микроконтроллеры разных моделей имеют собственный набор периферийных устройств, называемых так, поскольку ядром микроконтроллера, его главным устройством, всегда является микропроцессор, называемый центральным процессором. Все остальные устройства микроконтроллера являются устройствами вспомогательными, и соответственно называются периферийными устройствами или периферией (а на жаргоне - фаршем).

Соответственно, разные модели микроконтроллеров имеют разные наборы прерываний и разные таблицы векторов прерываний.

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

Таким образом для каждого типа прерывания программист может определить отдельную функцию, которая будет по данному прерыванию вызываться. Что очень удобно. Например, прерывание по таймеру 1 - одна функция, по таймеру 2 - другая функция, при приёме очередного байта по последовательному интерфейсу - третья функция, и т.д. Это позволяет в каждой такой функции-обработчике прерывания разместить только тот код, который относится к данному событию, и недобавлять в неё ничего, что к данному вектору прерывания не относится.

Микроконтроллеры ATmega168 и ATmega328p, на основе которых сделан Arduino, отличаются друг от друга только размером памяти, и поэтому имеют одинаковый набор векторов прерываний. Единственная несовместимость между ними состоит в том, что таблица прерываний при использовании загрузчика располагается не в начале памяти программ, а в начале памяти загрузчика, и поскольку память загрузчика расположена в конце памяти программ, то этот адрес у них разный из-за разного размера этой самой памяти.

Прерывания этих микроконтроллеров определены в заголовочных файлах <iom328p.h> и <iom168.h> и выглядит это определение следующим образом:

/* Interrupt Vectors */
/* Interrupt Vector 0 is the reset vector. */
#define INT0_vect         _VECTOR(1)   /* External Interrupt Request 0 */
#define INT1_vect         _VECTOR(2)   /* External Interrupt Request 1 */
#define PCINT0_vect       _VECTOR(3)   /* Pin Change Interrupt Request 0 */
#define PCINT1_vect       _VECTOR(4)   /* Pin Change Interrupt Request 0 */
#define PCINT2_vect       _VECTOR(5)   /* Pin Change Interrupt Request 1 */
#define WDT_vect          _VECTOR(6)   /* Watchdog Time-out Interrupt */
#define TIMER2_COMPA_vect _VECTOR(7)   /* Timer/Counter2 Compare Match A */
#define TIMER2_COMPB_vect _VECTOR(8)   /* Timer/Counter2 Compare Match A */
#define TIMER2_OVF_vect   _VECTOR(9)   /* Timer/Counter2 Overflow */
#define TIMER1_CAPT_vect  _VECTOR(10)  /* Timer/Counter1 Capture Event */
#define TIMER1_COMPA_vect _VECTOR(11)  /* Timer/Counter1 Compare Match A */
#define TIMER1_COMPB_vect _VECTOR(12)  /* Timer/Counter1 Compare Match B */ 
#define TIMER1_OVF_vect   _VECTOR(13)  /* Timer/Counter1 Overflow */
#define TIMER0_COMPA_vect _VECTOR(14)  /* TimerCounter0 Compare Match A */
#define TIMER0_COMPB_vect _VECTOR(15)  /* TimerCounter0 Compare Match B */
#define TIMER0_OVF_vect   _VECTOR(16)  /* Timer/Couner0 Overflow */
#define SPI_STC_vect      _VECTOR(17)  /* SPI Serial Transfer Complete */
#define USART_RX_vect     _VECTOR(18)  /* USART Rx Complete */
#define USART_UDRE_vect   _VECTOR(19)  /* USART, Data Register Empty */
#define USART_TX_vect     _VECTOR(20)  /* USART Tx Complete */
#define ADC_vect          _VECTOR(21)  /* ADC Conversion Complete */
#define EE_READY_vect     _VECTOR(22)  /* EEPROM Ready */
#define ANALOG_COMP_vect  _VECTOR(23)  /* Analog Comparator */
#define TWI_vect          _VECTOR(24)  /* Two-wire Serial Interface */
#define SPM_READY_vect    _VECTOR(25)  /* Store Program Memory Read */
#define _VECTORS_SIZE (26 * 4)

Всего, как можно увидеть из значения определения _VECTORS_SIZE, векторов прерываний 26, и на каждый отводится 4 байта. Вектор прерывания 0 - это на самом деле вектор прерывания по нажатию кнопки сброс.

Для того, чтобы было удобнее, ниже приведена таблица с комментариями:

Вектора прерываний ATmega328p