Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Микропроцессоры и микроЭВМ. Учебное пособие
.pdf
почти не давая основной программе работать. Поэтому обычная схема
использования этого режима – сразу же по возникновении в начале обработчика его запретить (процедура обработки при этом, раз уж началась,
выполнится до конца) и разрешить опять только тогда, когда внешнее
воздействие должно уже закончиться (например, если это нажатие кнопки, то его следует опять разрешить по таймеру через одну-две секунды).
В отличие от этого, прерывания по фронту или спаду выполняются
один раз на каждый импульс. Конечно, от дребезга контактов там никакой
защиты нет и быть не может, потому что МК не способен отличить дребезг от серии коротких импульсов. Если это критично, нужно либо принимать внешние меры по защите от дребезга, либо прибегнуть к тому же
способу, что и для прерывания по уровню: внутри процедуры обработчика прерывания первой командой запретить само прерывание, а через некоторое время в другой процедуре (например, по таймеру или по иному
событию) опять его разрешить. Но если при нажатии кнопки просто какая-то переменная или вывод порта устанавливается в некое состояние, то
ничего страшного не случится, если оно установится несколько раз подряд, только следует учесть, что последний раз это может произойти с отпусканием кнопки.
2.5.1. Организация прерываний на ассемблере
Как было сказано выше в микроконтроллерах AVR адреса векторов
прерываний располагаются в начале памяти программ (табл. 2.3).
№
вектора
1
2.3. Векторы прерываний микроконтроллеров AVR
Адрес памяти
программ
Источник Описание прерывания
$0000 RESET Сброс по выводу и сторожевому
таймеру (Hardware Pin and
Watchdog Reset)
2
$0002 INT0 Запрос внешнего прерывания 0
(External Interrupt Request 0)
3
$0004 INT1 Запрос внешнего прерывания 1
(External Interrupt Request 1)
4
$0006 INT2 Запрос внешнего прерывания 2
(External Interrupt Request 2)
5
$0008 INT3 Запрос внешнего прерывания 3
(External Interrupt Request 3)
6
$000A INT4 Запрос внешнего прерывания 4
(External Interrupt Request 4)
7
$000C INT5 Запрос внешнего прерывания 5
(External Interrupt Request 5)
81

№
вектора
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Продолжение табл. 2.3
Адрес памяти
программ
Источник Описание прерывания
$000E INT6 Запрос внешнего прерывания 6
(External Interrupt Request 6)
$0010 INT7 Запрос внешнего прерывания 7
(External Interrupt Request 7)
$0012 TIMER2
COMP
Совпадение при сравнении таймера/счётчика 2 (Timer/Counter2
Compare Match)
$0014 TIMER2
OVF
$0016 TIMER1
CAPT
$0018 TIMER1
COMPA
Переполнение таймера/счётчика
2 (Timer/Counter2 Overflow)
Захват таймера/счётчика 1
(Timer/Counter1 Capture Event)
Совпадение A при сравнении таймера/счётчика 1 (Timer/Counter1
Compare Match A)
$001A TIMER1
COMPB
Совпадение B при сравнении таймера/счётчика 1 (Timer/Counter1
Compare Match B)
$001C TIMER1
OVF
$001E TIMER0
COMP
Переполнение таймера/счётчика
1 (Timer/Counter1 Overflow)
Совпадение при сравнении таймера/счётчика 0 (Timer/Counter0
Compare Match)
$0020 TIMER0
OVF
Переполнение таймера/счётчика
0 (Timer/Counter0 Overflow)
$0022 SPI, STC Завершение пересылки SPI (SPI
Ser ial Transfer Complete)
$0024 UART,
RX
$0026 UART,
UDRE
Завершение приёма UART
(UART, Rx Complete)
Регистр данных UART пуст
(UART Data Register Empty)
$0028 UART, TX Завершение передачи UART
(UART, Tx Complete)
$002A ADC Завершение ADC преобразова-
ния (ADC Conversion Complete)
$002C EE
READY
$002E ANALOG
COMP
Готовность EEPROM (EEPROM
Ready)
Срабатывание аналогового компаратора (Analog Comparator)
82

При написании программ на языке ассемблера для размещёния команды вектора по нужному адресу памяти программ может использоваться директива .ORG, которая присваивает абсолютное значение счётчику
команд. Параметром директивы является значение, которое должно быть
присвоено счётчику.
Пример:
.CSEG ;Начало сегмента кода
…
.ORG 0x1C ;Установить счётчик на значение 0x1С
jmp TIMER1 OVF ; Эта команда будет расположена в памяти про-
грамм по адресу 0x1C
Другим способом размещёния векторов прерываний является последовательное заполнение таблицы векторов прерываний в сегменте кода
как показано в следующем листинге:
Адрес Метка Код Комментарий
$0000 jmp RESET ; Обработчик сброса (Reset Handler)
$0002 jmp EXT_INT0 ; Обработчик прерывания IRQ0 (IRQ0Handler)
$0004 jmp EXT_INT1 ; прерывания IRQ1 (IRQ1 Handler)
$0006 jmp EXT_INT2 ; прерывания IRQ2 (IRQ2 Handler)
…
$002C jmp EE_RDY ; готовности EEPROM
$002E jmp ANA_COMP ; срабатывания аналогового компаратора
$0030 MAIN: <instr> xxx ; Начало основной программы
... ... ... ...
Если какие-то вектора не используются и такого прерывания не возникнет в процессе работы программы, то вместо команд переходов jmp
ставится пустая команда nop.
Обработчик прерывания обычно располагается в конце программного кода, что вызвано удобством отладки, хотя разместить его можно и в
другом месте.
Пример обработчика прерывания:
…
TIMER1 OVF: ; метка входа в прерывание
команда1 ; команды обработчика прерывания
команда2
…
reti ;команда выхода из прерывания
83

2.5.2. Организация прерываний на языке Си
В различных компиляторах обработка прерываний реализована поразному, так как язык C старается оставаться подальше от машиннозависимых подробностей, в среде WinAVR используется предустановленная таблица векторов прерываний, содержащая адреса соответствующих
подпрограмм обслуживания с заранее определёнными именами. Для каждой такой подпрограммы в этом библиотечном файле определён макрос:
ISR(). Этот макрос регистрирует и помечает некоторую функцию как обработчик прерывания. Например, так выглядит определение обработчика
для прерывания от АЦП.
#include <avr/interrupt.h>
ISR(ADC_vect)
{
// Пользовательский код здесь
}
Директивой include подключается библиотека обработки прерываний, описание которой можно найти по адресу http://avrlibc.narod.ru/group__avr__interrupts.html. В качестве параметра макроса
указано имя вектора ADC_vect, которое закреплено за используемым
микроконтроллером.
Замечание. Для различных типов микроконтроллеров названия векторов могут одного и того же прерывания могут отличаться, поэтому его необходимо выбирать из таблицы, приведенной в описании библиотеки прерываний для соответствующего микроконтроллера.
Если происходит неожиданное прерывание (прерывания разрешены,
а никакого обработчика не установлено, что обычно указывает на ошибку), то по умолчанию происходит сброс микроконтроллера. Во избежание
этого, следует перекрыть библиотечную функцию__vector_default, что
можно сделать с помощью макроса ISR().
#include <avr/interrupt.h>
ISR(__vector_default)
{
// здесь пользовательский код
}
Аппаратные средства AVR сбрасывают флаг глобального разрешения прерываний в регистре SREG перед вводом вектора прерывания. Таким образом, дальнейшие прерывания запрещаются до выхода из обработчика обслуживаемого прерывания (до команды RETI, которая генерируется компилятором в конце обработки прерывания). По этой причине
84

программы обработки прерывания обычно не вкладывают друг в друга.
Для большинства программ обработки прерывания, это – желательное
поведение, для некоторых это даже требуется, чтобы предотвратить бесконечные рекурсивные прерывания (подобные UART).
Однако в редких случаях необходимо как можно раньше установить
флаг глобального разрешения прерываний. Это можно сделать, используя
sei () в начале программы обработки прерывания, но и в этом случае всё
ещё остаются несколько команд в сгенерированной компилятором вводной части, с запрещёнными вложенными прерываниями. Компилятор
можно проинструктировать, чтобы вставить право команды SEI в начале
программы обработки прерывания, используя следующий путь:
void XXX_vect(void) __attribute__((interrupt));
void XXX_vect(void)
{
...
}
где XXX_vect допустимое имя вектора прерывания для рассматриваемого
типа MCU (рассмотрено ниже).
Прерывание выбрано, если снабжено одним из разрешённых имён
векторов.
В последних версиях WinAVR допустимы две формы имён векторов.
Одна форма использует имена, типа SIG_XXX – это была единственная
доступная форма в avr-libc до версии 1.2.x. Начиная с avr-libc версии 1.4.0,
добавилась вторая форма имен вектора прерывания, XXX_vect, где XXX
соответствует векторному имени, как описано в datasheet-e соответствующего устройства (и в файлах Atmel) с пробелами, заменёнными символом подчеркивания, и исключены другие не алфавитно-цифровые символы. Использование суффикса _vect применено для того, чтобы улучшить совместимость с другими компиляторами Cи, доступным для AVR.
Форма SIG_XXX в будущем может стать осуждаемой, так что использовать её в новых проектах не рекомендуется.
85

3. ПРИМЕРЫ ПРОЕКТОВ НА МИКРОКОНТРОЛЛЕРАХ AVR
Пример программы на Си
Цель проекта состоит в разработке программного обеспечения, для
реализации управления яркостью светодиодов посредством широтноимпульсной модуляции (ШИМ) в соответствии с представленной схемой
электрической принципиальной.
Исходные данные:
1. Шаг изменения яркости 1%
2. Схема электрическая принципиальная (рис. 3.8)
VCC
PB7
PB0
PD6
19
12
11
20
R1
HL1
.. .. .. .. . . . . . . . .. .... .
R8 HL8
BA1
10
DD1
7
PD3
8
PD4
9
PD5
GND
Рис. 3.1. Схема электрическая принципиальная
Сопротивление каждого резистора составляет 240 Ом. Микросхема
DD1 – микроконтроллер Attiny 2313. В качестве динамика BA1 использу-
ется пьезоэлектический излучатель с встроенным генератором звуковых
частот.
В ходе проектирования необходимо составить блок-схемы процедур
и функций, определить способы формирования ШИМ режима и выбрать
прерывания для обработки событий.
Процедура прерывания ISR(TIMER1_COMPA_vect) представлена на
рис. 3.2.
86

Рис. 3.2. Блок-схема функции прерываний
87

Процедура подачи звукового сигнала beep(t) представлена на
рис. 3.3.
Рис. 3.3. Блок-схема функции подачи звукового сигнала
Процедура мигания выбранным каналом blink(n) представлена на
рис. 3.4.
Рис. 3.4. Блок-схема функции мигания выбранным каналом
Функция сканера кнопок представлена на рис. 3.5, а основная программа представлена на рис. 3.6.
88

Рис. 3.5. Блок-схема процедуры сканера кнопок
89

90
Рис. 3.6. Блок-схема основной программы
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
