Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

КР1 / КР №1 все

.pdf
Скачиваний:
32
Добавлен:
08.04.2022
Размер:
2.52 Mб
Скачать

8. Прерывания, вектор прерываний.

Прерывания – это аппаратные события, которые прекращают нормальный ход программы для выполнения какой-либо приоритетной задачи. При этом событие может быть как внутренним (от встроенной периферии самого микроконтроллера – таймеров, портов ввода-вывода, АЦП и других), так и внешним – например, появление на входе импульса от нажатой кнопки. Возникает вопрос, можно ли обрабатывать эти события без использования прерываний?

В наиболее простых случаях так и происходит: основная программа представляет собой бесконечный цикл, внутри которого тем или иным способом отслеживаются возникновения событий, при наступлении которых устанавливается определённое значение переменной, называемой обычно флагом (бит в специализированном регистре или ячейке памяти). Основная программа проверяет в цикле значения используемых флагов, и при их изменении переходит к обработке соответствующего события. Чем неудобен подобный подход? Во-первых, подобный цикл ожидания полностью загружает микроконтроллер, который в это время мог бы делать чтонибудь полезное. Во-вторых, некоторые события в принципе не могут долго ждать, например, обработка приёма данных по USART – если пропустить хоть один байт, логика работы программы будет нарушена, а повторная пересылка данных может быть не предусмотрена. Именно поэтому для организации более эффективного использования ресурсов микроконтроллера и используют прерывания.

Как работают прерывания. При возникновении прерывания микроконтроллер завершает текущую команду, сохраняет в стеке содержимое счетчика команд и совершает переход на адрес соответствующего вектора прерывания. По этому адресу, как правило, находится команда безусловного (JMP или RJMP) перехода к подпрограмме обработки прерывания. За каждым аппаратным прерыванием микроконтроллера закреплен свой адрес, и все вместе они образуют таблицу векторов прерываний, которая расположена в самом начале памяти программ. Поскольку у каждого микроконтроллера набор периферии разный, вектор прерываний также будет отличаться. Ниже приведена таблица векторов прерываний микроконтроллера ATTiny2313, который мы будем использовать вынуждены использовать в новых условиях при выполнении практических работ.

Таблица векторов прерываний микроконтроллера ATTiny2313

Адрес

Источник прерывания

Описание

 

 

 

 

1

.ORG 0x0000

RESET

External Pin, Power-on Reset

 

 

 

 

2

.ORG 0x0001

INT0

External Interrupt Request 0

 

 

 

 

3

.ORG 0x0002

INT1

External Interrupt Request 1

 

 

 

 

4

.ORG 0x0003

TIMER1 CAPT

Timer/Counter1 Capture Event

 

 

 

 

 

 

31

 

5

.ORG 0x0004

TIMER1 COMPA

Timer/Counter1 Compare Match A

 

 

 

 

6

.ORG 0x0005

TIMER1 OVF

Timer/Counter1 Overflow

 

 

 

 

7

.ORG 0x0006

TIMER0 OVF

Timer/Counter0 Overflow

8

.ORG 0x0007

USART0, RX

USART0, Rx Complete

 

 

 

 

9

.ORG 0x0008

USART0, UDRE

USART0 Data Register Empty

 

 

 

 

10

.ORG 0x0009

USART0, TX

USART0, Tx Complete

 

 

 

 

11

.ORG 0x000A

ANALOG COMP

Analog Comparator

 

 

 

 

12

.ORG 0x000B

PCINT

Pin Change Interrupt

 

 

 

 

13

.ORG 0x000C

TIMER1 COMPB

Timer/Counter1 Compare Match B

 

 

 

 

14

.ORG 0x000D

TIMER0 COMPA

Timer/Counter0 Compare Match A

 

 

 

 

15

.ORG 0x000E

TIMER0 COMPB

Timer/Counter0 Compare Match B

 

 

 

 

16

.ORG 0x000F

USI START

USI Start Condition

 

 

 

 

17

.ORG 0x0010

USI OVERFLOW

USI Overflow

 

 

 

 

18

.ORG 0x0011

EE READY

EEPROM Ready

 

 

 

 

19

.ORG 0x0012

WDT OVERFLOW

Watchdog Timer Overflow

 

 

 

 

 

.ORG INT_VECTORS_SIZE

Конец таблицы прерываний

Контроллер стартует с адреса 0x00 (нулевого адреса памяти программ). Далее мы делаем безусловный переход на метку RESET. Если этого не сделать, то контроллер начнёт выполнять команды из таблицы векторов прерываний, что нам совершенно не нужно. После перехода по метке первым делом необходимо проинициализировать стек. Потом, используя команду SEI, разрешаем глобальные прерывания. За разрешение конкретных прерываний для каждого вида периферии отвечают соответствующие регистры управления локальными прерываниями.

Когда возникает прерывание, выполнение текущих операций приостанавливается и микроконтроллер переходит по соответствующей метке на подпрограмму обработки прерывания. Последней командой подпрограммы

32

обработки прерывания должна быть команда RETI, которая обеспечивает возврат в основную программу и восстановление предварительно сохраненного счетчика команд и данных, заблаговременно перенесённых в стек.

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

Для глобального разрешения или запрещения прерываний предназначен флаг I регистра состояния SREG. Для разрешения работы прерываний он должен быть установлен в единицу (это делается с помощью ассемблерной команды SEI), а для запрещения сброшен (командой CLI). По умолчанию (после сброса микроконтроллера) этот флаг сброшен, и все прерывания микроконтроллера запрещены. Также возможно индивидуальное разрешение или запрещение (маскирование) прерываний, которое производится установкой или сбросом соответствующих разрядов регистров масок прерываний. Для каждого блока периферии существует собственный регистр для разрешения локальных прерываний. При возникновении прерывания флаг I регистра SREG сбрасывается на аппаратном уровне, запрещая тем самым обработку следующих прерываний. При возврате из подпрограммы обработки прерывания (при выполнении команды RETI) флаг I устанавливается обратно.

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

Прерывания второго типа не имеют флагов прерываний и генерируются

втечение всего времени, пока присутствуют условия, необходимые для генерации прерывания. Соответственно, если условия, вызывающие прерывание, исчезнут до разрешения прерывания, генерации прерывания не произойдет.

Наименьшее время отклика для любого прерывания составляет 4 машинных цикла, в течение которых происходит сохранение счетчика команд

встеке. В течение последующих двух или трех циклов выполняется команда перехода к подпрограмме обработки прерывания. Если прерывание произойдет во время выполнения команды, длящейся несколько циклов, то генерация прерывания произойдет только после выполнения этой команды.

33

Если же прерывание произойдет во время нахождения микроконтроллера в «спящем» режиме, время отклика увеличивается еще на 4 машинных цикла. Возврат в основную программу занимает 4 машинных цикла, в течение которых происходит восстановление счетчика команд из стека. После выхода из прерывания процессор всегда выполняет одну команду основной программы, прежде чем обслужить любое отложенное прерывание.

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

TIM0_OVF:

 

PUSH

R16

// Сохраняем регистр R16

IN R16, SREG // Перемещаем содержимое SREG в R16

PUSH

R16

// Сохраняем всё в стек

PUSH

R17

// R17 сохраняем туда же

……………

// Выполнение кода обработчика прерывания

POP R17

// Перед выходом из прерывания извлекаем

POP R16

// сохранённые данные

OUT SREG, R16 // Действуем при этом в обратном порядке

POP R16

 

RETI

// Выходим из прерывания

Также существует ряд операций, которые должны выполняться неразрывно, например, чтение 16-разрядного счетного регистра таймера. Поскольку ядро микроконтроллеров семейства Tiny 8-разрядное, то 16разрядный регистр таймера считывается (или записывается) в два приема – причём сначала считывается младший байт, а потом старший (это подробно рассматривалось в главе, посвящённой таймерам). Между двумя этими операциями не должно возникать никаких прерываний, поэтому перед чтением такого регистра необходимо их запретить, а после окончания операции чтения разрешить обратно.

9) Основы языка Assembler для микроконтроллеров семейства AVR. Синтаксис, классификация команд.

Язык ассемблера – система обозначений, используемая для представления в удобно читаемой форме программ, записанных в машинном коде. Команде языка ассмеблер один к одному соответствуют командам процессора. Фактически они представляют собой более удобную для человека символьную форму записи (мнемокоды) команд и их аргументов.

Кроме того, язык ассемблера позволяет использовать символические метки вместо адресов ячекк памяти, которые при ассмеблировании заменяются на

34

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

Каждая модель (или семейство) процессоров имеет свой набор команд и соответствующий ему язык ассемблера, микроконтроллеры семейства AVR не являются исключением. Теперь рассмотрим подробнее синтаксис ассемблера

AVR Studio 7.

Комментарии

Общее правило – чем подробнее описаны выполняемые команды, тем лучше. Обозначаются двумя способами - с помощью символа ; или //. Для объемных комментариев, занимающих несколько строчек, целесообразно использовать такую структуру: /* текст комментария */.

Операторы

Оператор .def позволяет присвоить любому регистру микроконтроллера некоторые осмысленное символьное имя. Например, если мы используем в качестве промежуточного хранилища регистр R16, намного проще присвоить ему имя Temp и в дальнейшем использовать уже его:

.def Temp = R16

Одному и тому же регистру можно присвоить несколько имен, но обратная операция недопустима.

Оператор .equ позволяет присвоить выражению или константе некоторую символьную метку. То есть, если какое-то число встречается в программе часто и нам понадобится его изменять, мы один раз меняем присвоенную ему метку вместо изменения всех чисел в тексте программы. Также с помощью этого оператора можно присвоить выражение. Примеры:

.equ XTAL = 4000000 // определяем тактовую частоту контроллера в МГц

.equ baudrate = 9600 // задаем скорость передачи данных Бит/с

.equ bauddriver = XTAL/(16*baudrate)-1 // вычисляем значение делителя

Оператор .include позволяет подключать в тело программы часть кода из другого текстового файла. Если необходимо подключить не весь

35

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

.macro – оператор макроподстановки. В языках ассемблера макрос – символьное имя, заменяемое при обработке препроцессором на последовательность программных инструкций. Он представляет собой последовательность команд, которые подставляются в нашу программу при вызове этого самого макроса.

Операнды

Программа для любого МК представляет собой последовательность команд, записанных в памяти программ. Большинство команд при выполнении изменяют содержимое одного или нескольких регистров общего назначения, регистров ввода/вывода или ячеек ОЗУ. Для обращения к различным областям адресного пространства памяти данных используются различные команды, реализующие, в свою очередь, различные способы адресации. Доступ к

регистрам ввода/вывода осуществляется по их адресам, являющимися операндами команды.

Мнемоническая запись команды выглядит следующим образом: сначала идет непосредственно сама команда, затем пробел, затем следуют операнды. Некоторые команды не имеют (RETI, NOP) или имеют только один операнд (INC/DEC). Если же команда имеет два операнда, сначала указывают приёмник, затем источник, причем между ними должна стоять запятая.

SUB R16, R17 // из содержимого R16 нужно вычесть содержимое R17, результат окажется в R16

Практически каждая команда занимает одну ячейку программы;

AVR-ассемблер не различает буквенный регистр;

Каждая команда должна занимать отдельную строку;

Числе по умолчанию считаются десятеричными, двоичные числа как в языке Си: 0b00010101;

Типы ассемблерных команд

Команды логических операций;

Команды арифметических операций и команды сдвига;

Команды операций с битами;

Команды пересылки данных;

Команды передачи управления;

Команды управления системой.

36

1. Команды логических операций.

Позволяют выполнять стандартные логические операции над байтами, такие как логическое умножение (И), логическое сложение (ИЛИ), операцию исключающее ИЛИ, вычисление обратного (дополнительного до единицы) и дополнительного (дополнение до двух) кода числа. Сюда также можно отнести команды очистки/установки регистров. Операции выполняются между регистрами общего назначения или между регистром и константой; результат сохраняется в РOН.

Все команды из этой группы выполняются за один машинный цикл.

2. Арифметические команды и команды сдвига.

В эту группу входят команды, которые позволяют выполнять такие базовые операции, как сложение, вычитание, сдвиг (влево и вправо), инкремент и декремент. В микроконтроллерах семейства Mega также есть команды, позволяющие умножать 8-битные значения. Все операции выполняются только над регистрами общего назначения. В то же время микроконтроллеры AVR позволяют легко работать как со знаковыми, так и беззнаковыми числами, а также работать с числами, представленными в дополнительном коде.

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

3. Команды операций с битами.

В эту группу входят команды, выполняющие установку или сброс заданного бита РOН или PBB. Более того, для изменения разрядов регистра состояния SREG существуют и дополнительные команды (точнее, эквивалентные мнемонические обозначения общих команд), поскольку чаще всего проверяется состояние битов именно этого регистра. Условно в эту группу также могут входить две команды передачи управления типа «проверка / пропуск», которые пропускают следующую команду в зависимости от состояния разряда РОН или РВВ. Все задействованные биты РВВ имеют свои собственные символические имена. Определения этих имен описаны в том же включаемом файле, что и определения символьных имен адресов регистров. Таким образом, после включения указанного файла в программу команды

37

вместо числовых значений номеров цифр смогут указывать свои символьные имена.

4. Команды пересылки данных.

Команды этой группы предназначены для пересылки содержимого ячеек, находящихся в адресном пространстве памяти данных. Разделение адресного пространства на три части (РОН, РВВ, ОЗУ) предопределило разнообразие команд данной группы. Пересылка данных, выполняемая командами группы, может производится в следующих направлениях: РОН РОН, РОН РВВ, РОН память данных. Также к данной группе можно отнести стековые команды PUSH и РОР позволяющие сохранять в стеке и восстанавливать из стека содержимое РОН.

На выполнение команд данной группы требуется в зависимости от команды от одного до трех машинных циклов.

5. Команды передачи управления.

В эту группу входят команды перехода, вызова подпрограмм и возврата из них и команды типа «проверка/пропуск», пропускающие следующую за ними команду при выполнении некоторого условия. Также к этой группе относятся команды сравнения, формирующие флаги регистра SREG и предназначенные, как правило, для работы совместно с командами условного перехода. В системе команд микроконтроллеров семейства имеются команды как безусловного, так и условного переходов. Команды относительного перехода (RJMP), а в микроконтроллерах семейства Mega также косвенного (IJMP) и абсолютного (JMP) безусловного перехода являются самыми простыми в этой группе. Их функция заключается только в записи нового адреса в счетчик команд. Команды условного перехода также изменяют содержимое счетчика команд, однако это изменение происходит только при выполнении некоторого условия или, точнее, при определенном состоянии различных флагов регистра SREG.

Команды вызова подпрограммы (ICALL, RCALL и СALL) работают практически так же, как и команды безусловного перехода. Отличие заключается в том, что перед выполнением перехода значение счетчика команд сохраняется в стеке. Кроме того, подпрограмма должна заканчиваться командой возврата REТ.

6.Команды управления системой.

NOP – пустая команда-заглушка;

38

SLEEP – перевод МК в режим пониженного энергопотребления;

WDR – сброс сторожевого таймера.

Все команды этой группы выполняются за один машинный цикл.

10.

Регистры

ввода-вывода.

Схема

устройства

вывода

микроконтроллера, управляющие регистры, режимы работы.

 

 

Все регистры ввода/вывода (в дальнейшем буду писать РВВ) условно

можно разделить на два типа:

 

 

 

 

- служебные регистры микроконтроллера,

 

 

 

 

- регистры, относящиеся к конкретным

периферийным устройствам.

 

Все регистры

ввода/вывода занимают

свое

адресное пространство в

памяти данных (SRAM) – от 32 до 95 (или в шестнадцатиричном счислении от $20 до $5F) и идут сразу за регистрами общего назначения, в так называемом адресном пространстве ввода/вывода. Каждый регистр восьмиразрядный и занимает память в один байт.

Всего МК может иметь 64 регистра ввода/вывода – максимальное число

(за редким исключением). В тоже время, если МК простенький и в нем мало устройств, и он использует меньшее число РВВ, в области памяти данных все равно резервируется 64 адреса. Некоторым, слишком навороченным МК,

стандартного значения в 64 РВВ недостаточно. В таких МК в адресном пространстве памяти данных выделяется еще дополнительно 160 ячеек памяти

для дополнительных регистров ввода/вывода.

Каждый регистр ввода/вывода имеет свой номер – от 0 до 63 (или в шестнадцатиричном виде – от $00 до $3F), который соответствует его адресу в адресном пространстве ввода/вывода. Адрес РВВ в адресном пространстве ввода/вывода и адреса соответствующих им ячеек в ОЗУ (памяти данных) не совпадают. Если регистр имеет номер 0, то в адресном пространстве ОЗУ он будет занимать 32 ячейку памяти (ведь сначала идут 32 регистра общего назначения, а за ними уже – РВВ). Для определения адреса РВВ в области

памяти

данных

необходимо

прибавить

к

его

номеру

32.

 

 

 

39

 

 

 

 

Помимо номера, каждый регистр имеет свое имя (буквенную аббревиатуру) –

для удобства программистов.

Для разных МК имена регистров, имеющих одинаковое назначение,

обычно совпадают, а вот номер регистра может отличаться. Но это не так и важно, потому, что при программирование оперируют в основном именами регистров.

К примеру, для управления портом ввода-вывода имеется три РВВ – один служит для задания направления работы порта (на вывод или ввод информации), второй для … рассмотрим в следующей статье. И так каждое устройство.

Кусочек из таблицы регистров ввода/вывода (первое число – номер регистра, и оно же его адрес в адресном пространстве РВВ, в скобках указывается адрес регистра в адресном пространстве памяти данных, т.е.

номер +32):

 

 

 

 

 

Стек, или указатель

стека – это специальный регистр,

который

предназначен

для

организации

стековой

памяти.

По мере заполнения ячеек памяти первые данные уходят в глубь стека, и

добраться до них можно, только вытащив сначала последние введенные данные. Допустим, если мы запишем в стек последовательно три числа: 10,20

и 30, то для того, чтобы затем извлечь из стековой памяти число 10,

предварительно придется извлечь числа 30 и 20. Т.е., значение записанное

последним всегда будет прочитано первым.

Для нас тоже очень удобно сохранять в стеке данные при входе в

40

Соседние файлы в папке КР1