Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы
Непрочитано 08.07.2007, 18:21  
Tibo
Прохожий
 
Регистрация: 08.07.2007
Сообщений: 2
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Tibo на пути к лучшему
По умолчанию Обработка прерываний.

Я думаю на вопросы по прерываниям отвечали уже не раз, но я не смог найти на свой.
Пусть имеется следующая программа:
1)Функция Авария. При переходе к ней запускается бесконечный цикл в котором происходит сигнализация, а также сброс флагов прерывания, и остановка таймер-счетчика.
2)Функция обработки прерывания по переполнению таймер-счетчика, в которой вызывается функция Авария.
Вопрос первый.
Если я сбрасываю флаг прерывания при его выполнении. Прерывание будет считаться оконченым и не будет мешать обработке других прерываний? Корректно ли это?
Вопрос второй.
Как грамотно при выполнении прерывания после его окончания, вернуться не к месту, где была прервана оснавная программа, а перейти в желаемую точку. К примеру прерывание возникло в цикле, а после его выполнения необходимо из цикла выйти.
Как это ораганизовать на СИ для WINAVR?
Я понимаю что можно ввести в цикл дополнительное условие... Но если циклов много?
Возможно ли использовать метки или что-то подобное им?

Буду признателен за ответы.
Реклама:
Tibo вне форума  
Непрочитано 09.07.2007, 11:45  
nokazus
Вид на жительство
 
Регистрация: 05.09.2006
Сообщений: 360
Сказал спасибо: 0
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
nokazus на пути к лучшему
По умолчанию

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

POP R16
POP R16

Данные (адрес с которого вызвано прерывание) игнорируем. Теперь записываем в стек адрес возврата на метку и даем команду выхода из прерывания. Для этого выполняем команды

LDI R16,Low(Label)
PUSH R16
LDI R16,High(Label)
PUSH R16
RETI

Не помню какая очередность записи байтов в стек, сначала младший, потом старший (как написано здесь) или наоборот. Проверьте сами. Переложить на С думаю сможете.

Удачи.
nokazus вне форума  
Непрочитано 09.07.2007, 18:32  
double_dash
Прописка
 
Аватар для double_dash
 
Регистрация: 15.10.2006
Сообщений: 130
Сказал спасибо: 0
Сказали Спасибо 2 раз(а) в 1 сообщении
double_dash на пути к лучшему
По умолчанию Re: Обработка прерываний.

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

Сообщение от Tibo
Как грамотно при выполнении прерывания после его окончания, вернуться не к месту, где была прервана оснавная программа, а перейти в желаемую точку. К примеру прерывание возникло в цикле, а после его выполнения необходимо из цикла выйти.
Я понимаю что можно ввести в цикл дополнительное условие... Но если циклов много?
Возможно ли использовать метки или что-то подобное им?
Ну использовать какую либо глобальную переменную-флаг все равно придется.
А выходить из глубоких циклов
если все дело происходит в какой либо функции
можно при помощи return
Код:
int flag = 0;

func()
 {
  for(i=0; i‹n; i++)
   {
     ....
     for(j=0; j‹m; j++)
      {
       ....
       if(flag) return;
       }
     }   
  }
double_dash вне форума  
Непрочитано 09.07.2007, 19:13  
EVGENIY1962
Гражданин KAZUS.RU
 
Регистрация: 27.07.2006
Сообщений: 659
Сказал спасибо: 0
Сказали Спасибо 4 раз(а) в 4 сообщении(ях)
EVGENIY1962 на пути к лучшему
По умолчанию

Если вам доступен стек,то можно выйти куда угодно,но лучше этого не делать.Любой просчет приведет к сбою программы.Вы не слишком усердствуете?Кроме того вам придется отслеживать глубину стека и решать куда нужно выйти.Кстати стек придется править.
EVGENIY1962 вне форума  
Непрочитано 09.07.2007, 21:57  
sanitar249
Почётный гражданин KAZUS.RU
 
Аватар для sanitar249
 
Регистрация: 19.01.2007
Сообщений: 1,747
Сказал спасибо: 2
Сказали Спасибо 46 раз(а) в 35 сообщении(ях)
sanitar249 на пути к лучшему
По умолчанию

Вы затронули очень серьезный вопрос, с точки зрения программирования: "В фон-неймановской архитектуре единая область памяти используется, в том числе, и для реализации стека. При этом снижается производительность устройства, так как одновременный доступ к различным видам памяти невозможен. В частности, при выполнении команды вызова подпрограммы следующая команда выбирается после того, как в стек будет помещено содержимое программного счетчика.
В гарвардской архитектуре стековые операции производятся в специально выделенной для этой цели памяти. Это означает, что при выполнении программы вызова подпрограмм процессор с гарвардской архитектурой производит несколько действий одновременно.
Необходимо помнить, что МК обеих архитектур имеют ограниченную емкость памяти для хранения данных. Если в процессоре имеется отдельный стек и объем записанных в него данных превышает его емкость, то происходит циклическое изменение содержимого указателя стека, и он начинает ссылаться на ранее заполненную ячейку стека. Это означает, что после слишком большого количества вызовов подпрограмм в стеке окажется неправильный адрес возврата. Если МК использует общую область памяти для размещения данных и стека, то существует опасность, что при переполнении стека произойдет запись в область данных либо будет сделана попытка записи загружаемых в стек данных в область ОЗУ." Я полностью согласен с EVGENIY1962, что стек лучше "руками" не трогать. А для нормальной работы стека правильно расставить приоритеты прерываний, осуществить контроль заполнения стека и при угрозе переполнения отказывать в обработке малозначительным процессам(ставить в очередь, если возможно).
sanitar249 вне форума  
Непрочитано 10.07.2007, 07:31  
nokazus
Вид на жительство
 
Регистрация: 05.09.2006
Сообщений: 360
Сказал спасибо: 0
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
nokazus на пути к лучшему
По умолчанию

В программах на ассемблере состояние стека легко контролируется. И потом можно запоминать и состояние стека в переменной, а перед выходом восстанавливать указатель на адрес возврата. Я согласен, что это не совсем "правильно", но вполне возможно. "Правильней" создать переменную, в которую при обработке прерывания будет записываться признак или флаг, обзовите как угодно, а втеле программы эта переменная анализируется и происходит ветвление программы.
Но во-первых, обработчик прерываний вызывается из неопределенного места программы и возврат из прерывания произойдет в ту же неизвестную точку. Во-вторых обработка ветвлений занимает достаточно много времени и оно меняется от значения анализируемой переменной. А если человеку необходима немедленная реакцияна на событие?
Конечно все зависит от правильного (уже без кавычек) построения алгоритма программы. Выходить из прерывания описанным мной методом не рекомендуется при сложной программе. И не из-за стека, а из-за неопределенного состояния портов, переменных. Т.е. нужно уходить в процедуру реинициализации контроллера. Я думаю что в случае ухода на обработку критической ошибки, после которой следует процедура инициализации всего или рестарт программы это оправдано.
Я применял такой метод ветвления в теле прграммы (не при выходе из прерывания) с целью сократить время на обработку ветвлений при их большом количестве. К тому же, как я писал выше, это время не зависит от проверяемого значения. Строится таблица переходов в виде массива слов, где значение с индексом 0 является адресом на который нужно уходить если значение переменной равно 0 и т.д. Если кому интересно могу подробней описать.
Мой знакомый коллега использовал такой же метод и при выходе из прерывания. Все у него работает.
Не надо бояться, следует опасаться.
Конечно за стеком нужно следить, особенно при работе в Си.
Удачи.
nokazus вне форума  
Непрочитано 10.07.2007, 10:46  
bamu
Прохожий
 
Регистрация: 17.11.2006
Сообщений: 1
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
bamu на пути к лучшему
По умолчанию

Для обработки ошибок в WINAVR лучше использовать
функции setjmp и longjmp модуля ‹setjmp.h›,
пример использования приведен в
WinAVRdocavr-libcavr-libc-user-manual.
bamu вне форума  
Непрочитано 10.07.2007, 12:27  
EVGENIY1962
Гражданин KAZUS.RU
 
Регистрация: 27.07.2006
Сообщений: 659
Сказал спасибо: 0
Сказали Спасибо 4 раз(а) в 4 сообщении(ях)
EVGENIY1962 на пути к лучшему
По умолчанию

Сообщение от bamu
Для обработки ошибок в WINAVR лучше использовать
функции setjmp и longjmp модуля ‹setjmp.h›,
пример использования приведен в
WinAVRdocavr-libcavr-libc-user-manual.
Согласен.GOTO проще и безопаснее CALL.Про авр не знаю но в мелких пиках до стека прото так не добраться.
EVGENIY1962 вне форума  
Непрочитано 10.07.2007, 12:33  
SasaVitebsk
Гражданин KAZUS.RU
 
Регистрация: 04.08.2006
Сообщений: 911
Сказал спасибо: 28
Сказали Спасибо 180 раз(а) в 139 сообщении(ях)
SasaVitebsk на пути к лучшему
По умолчанию

В основном Вам ответили.
Про прерывания я соглашусь с double_dash. Это найболее коректный ответ на мой взгляд.

По выходу.
Действительно бывают такие ситуации (обычно аварийные) когда из любого места программы (в том числе из прерывания) лучше выйти в конкретное место. Обработчика аварии. Во всяком случае я такое делал. Как и другие я выполнял это на ассемблере. В добавление тех способов что вам перечислии (1. подсовывание адреса в стэк и возврат, 2. сброс стека и прямой переход) я добавлю ещё один. Инициализация стека и прямой переход. В принципе 1 и 3 способ можно реализовать на IAR C. С GCC к сожелению не знаком. Но я рекомендовал бы сделать следующее (если другим способом - ну никак)

По аварии выходить на JMP 0. А при инициализации проверять как мы попали в место старта. В этом случае у вас гарантированно будет всё нормально со всеми вашими переменными и стеками. (в смысле они инициализируются) Теже которые нельзя трогать необходимо разместить в сегменте неинициализированных.
Короче совтовый вариант WDT.
SasaVitebsk вне форума  
Непрочитано 10.07.2007, 13:18  
nokazus
Вид на жительство
 
Регистрация: 05.09.2006
Сообщений: 360
Сказал спасибо: 0
Сказали Спасибо 3 раз(а) в 3 сообщении(ях)
nokazus на пути к лучшему
По умолчанию

Сообщение от SasaVitebsk
По аварии выходить на JMP 0. А при инициализации проверять как мы попали в место старта. В этом случае у вас гарантированно будет всё нормально со всеми вашими переменными и стеками. (в смысле они инициализируются) Теже которые нельзя трогать необходимо разместить в сегменте неинициализированных.
Короче совтовый вариант WDT.
Вариант с аппаратным WDT или вызовом его срабатывания из программы - "5". При этом инициализируются все регистры микроконтроллера. Вариант же GOTO из прерывания на точку старта, даже если Вы всю периферию и переменные проинициализировали, в т.ч. указатель стека, может привести к неприятным последствиям. Пример, в MSC-51 имеется служебный недоступный регистр обработчика прерываний, который устанавливается вначале обработки прерывания и сбрасывается только командой RETI (этим она и отличается от команды RET) или системой сброса. Пока триггер не сбросится, обработки прерываний не будет. К сожалению про этот триггер мало написано в даташите. Не уверен, есть-ли такое в AVR, скорее нет. Но я бы не рискнул выходить из прерывания без RETI, или проверил бы.
Удачи.
nokazus вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Симуляция прерываний в EWAVR woroba Микроконтроллеры, АЦП, память и т.д 5 13.02.2009 08:39
Обработка нескольких прерываний AVR (вопрос) festoon Микроконтроллеры, АЦП, память и т.д 27 17.11.2008 18:02
обработка клавиатуры? maxNTF Микроконтроллеры, АЦП, память и т.д 18 26.10.2007 23:44
нид хелп. Обработка сигнала с датчика freele Автоматика и аппаратура связи 5 14.07.2007 16:56
Использование прерываний в ATMega8535 igor727 Микроконтроллеры, АЦП, память и т.д 2 28.04.2007 15:50


Часовой пояс GMT +4, время: 16:22.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot