Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Реклама ⓘ

Прерывания

Прерывания – это специальный механизм, позволяющий остановить выполнение основной программы и переключить процессор на выполнение другой задачи по определенному внешнему или внутреннему событию. Фактически прерывания являются обыкновенными подпрограммами, которые в тот или иной момент времени микропроцессор может вызывать аппаратно. Такие подпрограммы принято называть обработчиками прерываний.

В большинстве случаев прерывания позволяют очень сильно разгрузить ЦПУ от той работы, которую самостоятельно могут выполнять отдельные его модули. Например, любой таймер-счетчик, отсчитав необходимое число тактов генератора, может сгенерировать прерывание и вызвать подпрограмму, в которой будет находиться код для отчета различных временных интервалов. Точно таким же образом при наступлении определенного события (отсылка или прием слова данных, изменение состояния на линии и мн. др.) способны оповещать процессор модули USART, SPI, TWI, ADC и т.д. Различные модели AVR могут содержать от 4 до 56 таких источников прерываний.

Табл.5. Таблица векторов прерываний:

Номер

Адрес в памяти программ

Бит разрешение прерывания

Флаг прерывания

Описание события

1

0x0001

INT0 из GICR

INTF0 из GIFR

Внешнее прерывание 0   

2

0x0002

INT1 из GICR

INTF1 из GIFR

Внешнее прерывание 1

3

0x0003

OCIE2 из TIMSK

OCF2 из TIFR

Cовпадение TCNT2 и OCR2  

4

0x0004

TOIE2 из TIMSK

TOV2 из TIFR

Переполнение TCNT2   

5

0x0005

TICIE1 из TIMSK

ICF1 из TIFR

Захват в ICP1   

6

0x0006

OCIE1A из TIMSK

OCF1A из TIFR

Совпадение TCNT1 и OCR1A 

7

0x0007

OCIE1B из TIMSK

OCF1B из TIFR

Совпадение TCNT1 и OCR1B 

8

0x0008

TOIE1 из TIMSK

TOV1 из TIFR

Переполнение TCNT1   

9

0x0009

TOIE2 из TIMSK

TOV2 из TIFR

Переполнение TCNT0   

10

0x000A

SPIE из SPCR

SPIF из SPSR

Прерывание от модуля SPI 

11

0x000B

RXCIE из UCSRB

RXC из UCSRA

Получение байта по USART  

12

0x000C

UDRIE из UCSRB

UDRE из UCSRA

Опустошение UDR в USART   

13

0x000D

TXCIE из UCSRB

TXC из UCSRA

Передача байта по USART   

14

0x000E

ADIE из ADCSRA

ADIF из ADCSRA

Прерывание от АЦП   

15

0x000F

EERIE из EECR

EEMWE из EECR

Завершение записи в EEPROM

16

0x0010

ACIE из ACSR

ACI из ACSR

Прерывание от компаратора 

17

0x0011

TWIE из TWCR

TWINT из TWCR

Прерывание от модуля TWI  

18

0x0012

SPMIE из SPMCR

SPMIE из SPMEN

Завершение выполнения spm 

За каждым обработчиком прерывания жестко закреплен определенный адрес (вектор прерывания) в начале памяти программ. Положения векторов прерываний для ATmega8 сведены табл.5. Обычно по адресу вектора прерывания находится инструкция перехода, которая передает управление подпрограмме обработчика:

             .cseg
             .org 0       ;начало с нулевого адреса памяти программ

       rjmp  initial      ;переход на начало основной программы                                      
       rjmp  service_INT0 ;переход на метку service_INT0     
       rjmp  service_INT1 ;переход на метку service_INT1
       .
       rjmp  service_TWI  ;переход на метку service_TWI  
       rjmp  service_SPMR ;переход на метку service_SPMR

В моделях AVR с объемом FLASH ≤8 кбайт, для векторов отводится по 1 слову памяти программ, как раз для инструкций rjmp. Во всех остальных микроконтроллерах каждый вектор прерывания занимает уже 2 слова, а в качестве инструкции перехода используются jmp.

Управление прерываниями производится индивидуально. За разрешение каждого из них отвечают специальные разряды соответствующих РВВ, а о наступлении события микроконтроллер может судить по состоянию флагов прерывания (см. табл.5). Например, если прерывание по переполнению таймера-счетчика 2 разрешено (установлен бит TOIE2 из TIMSK), то при изменении содержимого счетного регистра TCNT2 c 0xFF на 0x00 в регистре TIFR аппаратно будет установлен флаг прерывания TOV2 и микроконтроллер вызовет подпрограмму по адресу 0x0004.

За общее управление прерываний у AVR отвечает флаг I из регистра SREG. При I=0 все прерывания, независимо от состояния битов разрешения, запрещены. 

При вызове обработчика прерывания адрес текущей команды в основной программе копируется в стек, как и при обычном вызове подпрограммы. Но вместе с этим микроконтроллер аппаратно сбрасывает на нуль флаг I и флаг, который явился источником прерывания. Обработчик должен заканчиваться командой возврата из прерывания reti. После ее выполнения адрес возврата восстанавливается в PC и при этом одновременно устанавливается флаг I.

Ниже рассмотрен пример использования обработчика внешнего прерывания INT0.

   .include "m8def.inc"    ;подключение стандартного заголовочного файла       

        .cseg              ;начало секции кода с нулевого адреса
        .org  0        

    rjmp  main             ;вектор сброса 
    rjmp  service_INT0     ;вектор внешнего прерывания 0
   .

main:
    ldi   R16,low(RAMEND)  ;инициализируем указатель стека
    out   SPL,R16
    ldi   R16,high(RAMEND)                 
    out   SPH,R16
    cbi   PORTD,PD2     ;настраиваем на ввод линию 2 порта D (альтернативная    
    sbi   DDRD,PD2      ;функция INT0) и подключаем к ней внутренний резистор
    ldi   R16,1«ISC01   ;задаем условием прерывания изменения 
    out   MCUCR,R16     ;состояния вывода INT0 с лог.1 на лог.0
    ldi   R16,1«INT0    ;разрешаем прерывание INT0
    out   GICR,R16      
    sei                 ;разрешаем прерывания глобально (I=1)
   .

service_INT0:
    push  R16           ;сохраняем в стеке R16
    in    R16,SREG
    push  R16           ;сохраняем в стеке SREG
   .
    pop   R16           ;восстанавливаем из стека SREG
    out   SREG,R16
    pop   R16           ;восстанавливаем из стека R16
    reti   

Инструкция перехода, размещенная по нулевому адресу (вектор сброса у всех моделей AVR), передает управление на начало основной программы main, где и происходит инициализация микроконтроллера. В качестве условия возникновения прерывания выбрано изменение состояния вывода INT0 с уровня лог.1 на лог.0 (момент нажатия кнопки). При возникновении указанного события произойдет вызов подпрограммы по адресу 0x0001 (вектор прерывания INT0) и, далее, обработчика service_INT0. В обработчике нужно сохранить содержимое SREG и, если это необходимо, остальных регистров, которые используются в контексте основной программы.

Возможна такая ситуация, что в процессе работы одновременно возникнут сразу несколько запросов на прерывания (одновременно будут установлены несколько флагов прерывания). В этом случае первым будет вызван тот обработчик, чей адрес в таблице векторов прерывания находится выше. Например, при возникновении запросов от АЦП (адрес 0x000E) и компаратора (адрес 0x0010), первым будет обработан запрос от АЦП. Таким образом, каждое прерывание у AVR имеет свой собственный неизменный приоритет, который зависит от его местоположением в таблице векторов.

Здесь возможны две проблемы. Во-первых, обработка отдельных прерываний может быть достаточно длительной процедурой и другие запросы окажутся отложенными на недопустимо большой срок. А во-вторых, прерывание с низким приоритетом может иметь намного большее значение для данного устройства. В обоих случаях можно выйти из положения, если допустить в программе вложенные прерывания. Для этого после сохранения контекста в обработчике прерывания нужно вручную установить флаг I командой sei:

service_INT0:
    push  R16           ;сохраняем в стеке R16
    in    R16,SREG
    push  R16           ;сохраняем в стеке SREG
    sei                 ;разрешаем прерывания во время обработчика 
   .
    pop   R16           ;восстанавливаем из стека SREG
    out   SREG,R16
    pop   R16           ;восстанавливаем из стека R16
    reti

Вложенные прерывания могут оказаться недопустимыми при малом размере стека.

Перейти к следующей части:

Теги:

Котов Игорь Юрьевич Опубликована: 2012 г. 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (1) | Я собрал (0) | Подписаться

0
Андрей #
cbi PORTD,PD2 ;настраиваем на ввод линию 2 порта D (альтернативная
sbi DDRD,PD2 ;функция INT0) и подключаем к ней внутренний резистор
Наоборот. Если сделать как вы пишете, то PD2 будет настроен на выход, так как записана единица в регистр DDRD. И при старте будет на нем лог нуль, так как записан ноль в PORTD.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется электрическая мощность?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Программатор Pickit3
Программатор Pickit3
Конструктор - темброблок на LM1036 Автомобильный GPS-трекер с GSM/GPRS и дистанционным управлением
вверх