AVR Урок 42. EXINT или внешние прерывания
Урок 42
EXINT или внешние прерывания
Вот наконец-то и настало время нам попробовать поработать с внешними прерываниям. Данный урок, во-первых, был очень востребован, хотя он и кажется на первый взгляд несложным. Очень много было просьб и я не мог не откликнуться. Во-вторых, мы сейчас работаем с модулем LAN ENC28J60, у которго имеется выход, по которому мы можем получить прерывания по окончании определённых операций, которые я и хотел обработать. Также, если у меня получится, я хотел этим поделиться и с вами, но без первоначального представления о внешних прерываниях в контроллере AVR это понять, я считаю, будет, мягко говоря, нелегко. Вот поэтому и созрел данный урок.
Так как я случайно залочил свой контроллер ATMega328, расположенный на недорогой плате, то работать мы будем с платой Arduino UNO.
Нет, не пугайтесь, мы не будем работать со средой программирования Arduino IDE, мы также будем работать с тем же самым Atmel Studio, только Arduino мы будем использовать в качестве отладочной платы и будем его программировать через разъём ISP.
Так что вы можете использовать по-прежнему любые отладочные платы. Но если вдруг кто-то решит использовать так же, как и я, Arduino UNO или любую другую Arduino, то предупреждаю заранее – после этого уже работать с ней Вы не сможете через стандартную среду программирования – Arduino IDE, так как загрузчик мы в случае прошивания через ISP затираем. Но это не смертельно, так как его можно будет впоследствии восстановить. Правда это занятие не из лёгких, но если есть интерес к восстановлению загрузчиков Arduino после их затирания программированием через ISP, то я могу по этому поводу написать статью и дать видеоурок.
Вообщем, пока не приедут платы более мелкие, я буду свои уроки писать с применением Arduino UNO, также и с модулем LAN я также буду работать с той же платой.
Также чем оказался хорош Arduino, что к нему не требуется переходник TTL-USB, так как он там уже прекрасно аппаратно реализован. Причём, мало того, мы через штатный USB-разъём Arduino не только будем пользоваться USART-ом, но и питать наш Arduino будем через него же.
В качестве программатора мы также будем использоваь дешёвый USBASP. Так как он у меня с переключателем пиания 3,3В/5В, то убрав с него совсем перемычку, мы вообще отключим питание с программатора на плату и будем через ISP исключительно только программировать нашу плату.
Так как на плате Arduino находится 6-контактный разъём ISP, то будем использовать стандартный ISP-переходник
После подключения программатора к плате мы получим вот такую картину
Подключим раъём USB к компьютеру – теперь у нас есть готовый выход USART на ПК, а также и питание
Вернёмся к нашим прерываниям. Внешние прерывания – это такие прерывания, которые обрабатываются вследствие возникновения некоторых событий на определённой ножке порта микроконтроллера. Таких событий существует несколько. Прерывания у контроллера AVR могут срабатывать как по уровню, так и по фронту. По уровню они срабатывают, когда будет замечен определённый логический уровень. То есть, если будет настроено срабатывание по уровню логической единицы, то если данный уровень будет оставаться на ножке внешнего прерывания, то прерывание будет срабатыать циклично, пока не установится другой логический уровень. А по фронту – когда будет замечен переход из одного логического состояния в другое. Фронт, как известно бывает восходящий или нисходящий. Говорят ещё вместо восходящего просто фронт, а вместо нисходящего – спад. Также ещё называют передний и задний фронт. Вообщем – это кому как удобно.
Ножек для отслеживания внешних прерываний у контроллера существует две – INT0 и INT1. Первая ножка совпадает с ножкой порта PD2, а вторая – с PD3
Теперь немного по аппаратной организации внешних прерываний. Вышеуказанные ножки назначены по умолчанию, но их можно и менять. Для этого есть в контроллере определённые регистры. Но данная тема сегодня рассматриваться не будет, мы будем работать именно с ножками вышеуказанными, поэтому и регистры мы рассмотрим только нужные нам.
Первый регистр – это регистр управления типом обрабатываемого события – EICRA
Пара битов ICS01 и ICS00 управляет типом событий на ножке INT0, а вторая – ICS11 и ICS10 – INT1
Вот зависимость типов событий от включения битов ICS01 и ICS00
А это для ICS11 и ICS10
Соответственно получим мы следющую зависимость:
00 – Низкий уровень на ножке,
01 – Любое изменение на ножке,
10 – нисходящий фронт на ножке,
11 – восходящий фронт на ножке.
Второй регистр – это регистр включения ножки прерываний EIMSK
В данном регистре существует всего два бита, разрешающих прерывания на соответствующих ножках – INT1 и INT0. Биты так и называются, поэтому не перепутаем.
Третий регистр – регистр флагов EIFR, устанавливаемых и сбрасываемых при определённых событиях
Напрямую мы к данному регистру не обращаемся, так как работать будем с функцией-обработчиком.
Теперь вроде что-то прояснилось по вопросу внешних прерываний.
Осталось дело за малым. Создать и прошить проект, который будет как-то наглядно демонстрировать работу внешних прерываний.
Запустим Atmel Studio 7, создадим проект с именем EXTI01, выберем контроллер ATmega328P, добавим в main.c функцию инициализации портов port_ini, в которой включим ножку светодиода на выход. Светодиод на плате располагается на ножке B6
void port_ini ( void )
//Включим ножку светодиода на выход
DDRB |= 0b00100000;
Вызовем данную функцию в main()
int main ( void )
port_ini ();
while (1)
Подключим кнопку между ножкой PD2 (D2) и общим проводом
Вернёмся в проект и напишем функцию инициализации внешних прерываний. Настроим нисходящий фронт, так как резистор для исключения неопределённого состояния на ножке мы можем подтянуть программно только к питанию и у нас в обычном состоянии на ножке будет логический 1
void int_ini ( void )
//включим прерывания INT0 по нисходящему фронту
EICRA |= (1 ISC01 );
//разрешим внешние прерывания INT0
EIMSK |= (1 INT0 );
Вызовем данную функцию в main(), а также не забываем включить глобальные прерывания
int_ini ();
sei ();
Давайте ещё на всякий случай настроим данную ножку на вход и подтянем резистор к питанию. В данной ситуации лучше резистор подтянуть, так как может возникнуть неопределённое состояние. Для этого добавим соответствующий код в функцию port_ini
//Включим ножку INT0 (PD2) на вход
//Подтянем резистор на ножке INT0 (PD2) к питанию
PORTD |= 0b00000100;
Также ещё нам необходимо добавить сам обработчик прерывания, в котором мы по возникновению настроенного события на ножке порта будем зажигать наш светодиод
ISR ( INT0_vect )
PORTB |= 0b00100000;
Соберём код, прошьём контроллер и попробуем нажать кнопку
Как мы видим, светодиод у нас загорелся.
Теперь давайте попробуем также испытать и другую ножку – INT1.
Для этого сначала настроим данную ножку в port_ini()
//Включим ножки INT0 и INT1 (PD2 и PD3) на вход
(0b00001100);
//Подтянем резисторы на ножках INT0 и INT1 (PD2 и PD3) к питанию
PORTD |= 0b00001100;
Затем перенастроим прерывания с учётом данной ножки и в функции int_ini()
//включим прерывания INT0 и INT1 по нисходящему фронту
EICRA |= (1 ISC11 )|(1 ISC01 );
//разрешим внешнее прерывание INT0 и INT1
EIMSK |= (1 INT1 )|(1 INT0 );
А вот обработчик у данной ножки свой отдельный, поэтому добавим его и светодиод в нём будем гасить
ISR ( INT1_vect )
Теперь мы можем подключить ещё кнопку на ножку PD3 (D3), воторым проводм также подключив её к общему проводу, собрать код, прошить контроллер и понажимать кнопки и отследить результаты изменения уровней по светодиоду
Теперь, если мы соберём код и прошьём контроллер, то первая кнопка будет у нас светодиод зажигать, а вторая тушить.
Казалось бы, что тут такого? А то, что происходит это уже независимо от хода самой программы, не в бесконечном цикле, когда во время там написанного обработчика по нажатию кнопки мы можем вообще не находиться и будет уже не ясно, обработается ли наше событие. Поэтому, изучив внешние прерывания, мы сделали большой шаг вперёд к независимости обработки тех или иных событий на ножках портов микроконтроллера. Конечно, учитывая наш уже теперь очень богатый опыт, нам было это проделать не очень тяжело.
Приобрести плату Arduino UNO R3 можно здесь.
Смотреть ВИДЕОУРОК (нажмите на картинку)
Источник
Не входит в прерывание в Atmel Studio 6
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Как реализовать прерывание по переполнению таймера atmega32a в Atmel Studio 4
Здравствуйте! Пытаюсь постигнуть таймеры. Но что-то не получается даже простенькое и понять не.
Почему AVR Studio 4, а не Atmel Studio 6?
По какой причине большинство специалистов по AVR микроконтроллерам в основном используют AVR Studyo.
Отладчик KEIL5.13 не входит в прерывание в пошаговом режиме
Добрый день, уважаемые коллеги. Имеем KEIL5.13 и плату STM32VLDyscovery (STM32F100RBT.
Atmel studio 6.1
Здравствуйте. столкнулся с проблемой запуска программы. вылетает сообщение:debugging tool is not.
Вложения
| main.txt (3.0 Кб, 3 просмотров) | |
| lcd.txt (3.3 Кб, 1 просмотров) | |
| new 1.txt (1.0 Кб, 1 просмотров) | |
| new 2.txt (521 байт, 1 просмотров) |
И уберите запрет/разрешение прерываний из обработчика — они там как собаке пятое колесо.
Добавлено через 12 минут
Спасибо, помогло! Ещё бы разобраться с настройками дебаггера и оптимизации. 2 вечера мучался, чтоб вразумительное на лсд 16×2 вывести в Протеусе. как только код не переделыаал, и частоту уменьшал. пока уровень настроек не снизил. Сейчас тоже колдовал с ними, чтобы в пошаговом режиме функция отправки командного байта отсылалась в ЛСД. Причем оптимизация решает за меня не особо корректно — у меня в этойфункции стоит переменная, в зависимости от которой работает/не работает определённый код в обработчике ррерывания
Atmel Studio
помогите написать программу работы светофора на языке Assembler
Atmel Studio 6.0
Здравствуйте! Подскажите пожалуйста , не пойму почему при запуске программы компилятор выдает : .
Atmel studio 6
Вопрос таков, есть некая библиотека, в lcd_lib.h прототипы, в lcd_lib.c сами функции, оба файла.
Atmel Studio
Подскажите где смотреть библиотеку Atmel Studio.
Источник
Прерывание на контроллере AVR в Atmel AVR Studio
Первым делом о том что такое прерывание.
Прерывание ( interrupt ) — это своеобразная функция, которая будет выполнена при поступлении сигнала на какой нибудь вход контроллера.
При работе в AVR Studio прерывания создаются при помощи макросов ISR() , SIGNAL() и INTERRUPT(). Они помечают некоторую функцию как обработчик прерывания. Их различие в том, что INTERRUPT() и ISR() определяют функцию обработчик для случая, когда разрешено общее прерывание (обработчик может быть прерван), а SIGNAL() для случая когда общее прерывание запрещено.
На этом покончим с теорией и перейдём к практике (хотя теории ещё будет ниже).
Соберём в ISIS такую схему:
Как вы уже наверное догадались мы напишем прерывание (которое генерируется кнопкой) которое будет зажигать и тушить диод.
Итак, откройте студию и создайте стандартный проект.
Для использования прерываний включим заголовочный файл:
Условимся, что прерывание (физически) не будет включать выключать питание на ноге контроллера (как это делается я уже рассматривал), а всего лишь будет изменять флаг. При определённых значениях которого и будет включаться и выключаться диод.
Зададим этот флаг глобально:
Теперь объявим прерывание:
Как видите в скобках макроса указан так называемый вектор прерывания. Этот вектор указывает компилятору для какого входа будет сгенерировано прерывание. Для INT1 — это SIG_INTERRUPT1. Для АЦП (ADC) например это — SIG_ADC. (весь перечень отлично описан в книге «Шпак Ю.А. Программирование на языке Си для AVR и PIC микроконтроллеров».)
Теперь перейдём к функции main нашей «программы».
Нам необходимо разрешить прерывания в целом и для INT1 в частности:
Когда это сделано нужно настроить поведение прерывания. Оно может быть сгенерировано по разному.
Скачиваем datasheet (ссылка есть при создании проекта) и находим в разделе прерывания (interrupt) такую таблицу:
Думаю как перевести это вы и так поймёте.
Установим состояние генерации прерывания при каждом «логическом изменении на INT1».
Теперь установим весь порт С как выход:
Ну а это уже должно быть понятно:
Ждать не обязательно. Тем более что это уменьшает быстродействие. Но мне так хочется.
Программа целиком:
Компилируем hex и собираем схему в Proteus. Наслаждаемся работой прерывания при изменении положения кнопки.
Источник