Полная версия этой страницы:
Прерывания в AVR
archi2000
Nov 12 2006, 17:09
Хочу уточнить правильно ли я понял.
Если запрещены внешние прерывания, но случается несколько событий, то флаг прерывания устанавливается только один раз. Разрешаем прерывания и этот флаг сбрасывается и выполняется код прерывания по соответствующему вектору?
Теперь еще хочу такое запрограммировать - в соответсвующих регистрах ядра тоже запретить внешние прерывания, а не только коммандой CLI - флаг внешнего прерывания выставляется? Как долго этот флаг существует? Пока я его сам не сброшу или не выполнится вектор прерывания?
bodja74
Nov 12 2006, 17:25
Цитата(archi2000 @ Nov 12 2006, 20:09)

Хочу уточнить правильно ли я понял.
Если запрещены внешние прерывания, но случается несколько событий, то флаг прерывания устанавливается только один раз. Разрешаем прерывания и этот флаг сбрасывается и выполняется код прерывания по соответствующему вектору?
Теперь еще хочу такое запрограммировать - в соответсвующих регистрах ядра тоже запретить внешние прерывания, а не только коммандой CLI - флаг внешнего прерывания выставляется? Как долго этот флаг существует? Пока я его сам не сброшу или не выполнится вектор прерывания?
Поняли неправильно,есть флаг разрешения прерывания и есть флаг запроса прерывания.
Первый разрешает,второй сигнализирует.
Если не хотите прерываний ,не разрешайте.
Можете почитать в разделе "статьи" про всю "физику" работы здесь nix-06.nm.ru ,я думаю популярно обьяснил.
archi2000
Nov 12 2006, 17:39
Понимаю я может и правильно, но не правильно задал вопрос.
Итак флаг разшешения прерывания я пишу сам в регистре GICR. Флаг запроса прерывания выставляет внешнее событие.
Если флаг разрешения прерывания сброшен и прерывания запрещены коммандой CLI, то при появлении на выводе МК события выставляется ли флаг запроса именно этого внешнего прерывания?
Я думаю что выставляется и только один раз не зависимо от того сколько внешних событий случилось так как бит этого флага запроса прерывания только один. И будет этот флаг висеть ровно столько, пока я его сам не сброшу и проигнорирую это внешнее событие или не разрешу это прерывание и его не обработаю.
За сайт спасибо.
bodja74
Nov 12 2006, 17:54
Совершенно правильно .
Но с подобными маневрами не шутят,как вы правиьно заметели,и флаги запроса нужны,когда во время обработки прерывания возникает еще одно ,а флаг I еще не установлен командой reti.В противном будем терять прерывания.
archi2000
Nov 12 2006, 18:02
Спасибо, но я сам хочу задать время обработки этих внешних собыбий. Я экспериментирую с любительским устройством похожим на сигнализацию. Все работает хорошо, но есть помехи по цепям датчиков около 50 мсек длительностью. Сложно все заэкранировать, хочу програмно на это время заблокировать внешние прерывания и один раз в 50 мсек их разрешать. Также хочу чтобы таких импульсов было не один, а допустим 5 шт. и тогда тревога, иначе просто через определенное время этот флаг очистить. Сигнализация описана для наглядности, устройство немного другое.
bodja74
Nov 12 2006, 18:17
Если я правильно понял принцип,то есть другой способ,
по прерыванию от датчика,запускаем таймер,и уже от прерывания таймера в зависимости что нам нужно(импульс до определенной длительности или их количество) меряем что нам нужно.
archi2000
Nov 12 2006, 18:35
Таймера и приоритетность прерываний у меня используются. Время длительности полезных событий измеряется секундами. Импульс помехи иногда проскакивает один раз в 10 сек. Хочу так. Допустим за одну секунду 5 раз по 100 м сек было внешнее прерывание. Значит было полезное событие.
С таймером алгоритм подавления помехи нигде не встречал. Ну вобщем это слышал краем уха используется при подавлении дребезга клавиатуры. Но у меня условия другие. Если кнопку можно нажать второй раз на клавиатуре, то в моем случае в случае неправильного принятия решения немного строже ответственность, хотя и не так строго как в сигнализации. Думаю подобрать экспериментально эти пороги правильного обнаружения и ложной тревоги с помощью задержек времени и запрещения/разрешения внешних прерываний и подсчета в теле прерывания количества вызовов.
У меня звуковые датчики. Где посмотреть пример кода того метода с таймером о котором ты говоришь?
Спасибо за ответы.
bodja74
Nov 12 2006, 18:44
Ну все очень просто.
1 Пошел сигнал от датчика ,пошло прерывание INT
2 В прерывании INT запускаем таймер с прерванием от него через 1 секунду (например по совпадению)
3 Неспешно считаем количество INT дальше в том же прерывании от INT
4 По прерыванию от таймера ,смотрим сколько было INT ,если 5 УРАА!!!
archi2000
Nov 12 2006, 18:51
Так оно примерно сейчас и работает, таймер меряет время, но он запускается в основной программе и отсчитывает равные промежутки времени с помощью внешней переменной. Только у меня сейчас внешнее событие - это один импульс за 1 сек. Хочу чтобы импульсов было несколько и один раз в сек счетчик импульсов сбрасывать, если не достигли порога 5 шт.
Nanobyte
Nov 12 2006, 21:29
Цитата(bodja74 @ Nov 12 2006, 22:44)

...
3 Неспешно считаем количество INT дальше в том же прерывании от INT
...
1) Немного непонятно, как считать INT находясь в INT. Может, в таймере?
2) Тогда, находясь в прерывании, нужно разрешить другие прерывания командой SEI.
SasaVitebsk
Nov 13 2006, 00:50
Цитата(archi2000 @ Nov 12 2006, 21:02)

Спасибо, но я сам хочу задать время обработки этих внешних собыбий. Я экспериментирую с любительским устройством похожим на сигнализацию. Все работает хорошо, но есть помехи по цепям датчиков около 50 мсек длительностью. Сложно все заэкранировать, хочу програмно на это время заблокировать внешние прерывания и один раз в 50 мсек их разрешать. Также хочу чтобы таких импульсов было не один, а допустим 5 шт. и тогда тревога, иначе просто через определенное время этот флаг очистить. Сигнализация описана для наглядности, устройство немного другое.
У меня это штатная работа.
В телефонной линии (цифровой) применён импульсный трансформатор. При передаче сигнала и не очень качественном трансе возникает не одно а два прерывания (на фронт и выброс). Я в обработчике прерывания, перед выходом сбрасываю ложное прерывание.
Надо просто учитывать что сброс осуществляется записью единицы. Безусловно, что надо учесть время такого переходного процесса.
насчёт остального Вам уже пояснили.
archi2000
Nov 14 2006, 14:47
Еще прошу помощи - даташит на неродном языке.
Процессор Атмега 8 Регистр GIFR - выписка из даташита.
• Bit 7 – INTF1: External Interrupt Flag 1
When an event on the INT1 pin triggers an interrupt request, INTF1 becomes set (one).
If the I-bit in SREG and the INT1 bit in GICR are set (one), the MCU will jump to the corresponding
Interrupt Vector. The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always
cleared when INT1 is configured as a level interrupt.
• Bit 6 – INTF0: External Interrupt Flag 0
When an event on the INT0 pin triggers an interrupt request, INTF0 becomes set (one).
If the I-bit in SREG and the INT0 bit in GICR are set (one), the MCU will jump to the corresponding
Interrupt Vector. The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it. This flag is always
cleared when INT0 is configured as a level interrupt.
Почему для сброса флага нужно записывать лог. 1 если эта лог. 1 обозначает, что флаг прерывания установлен?
У меня используется прерывание по уровню, в даташите написано, что флаг постоянно сбрасывается.
В какой момент времени он сбрасывается?
Pyku_He_oTTyda
Nov 14 2006, 14:53
Цитата
Почему для сброса флага нужно записывать лог. 1 если эта лог. 1 обозначает, что флаг прерывания установлен?
Так придумали инженеры ATMEL, причем это работает

Я понимаю так, не "физически" записать 1, а сам факт записи 1
archi2000
Nov 14 2006, 14:58
Спасибо, я сам также думал, что когда там 1, то 1+1 будет 0 в двоичной системе и флаг сбросится.
А если флаг не установлен, т.е. в ячейке уже 0 - то запись туда 1 вызовет прерывание?
Мне непонятно, как вообще вызывается прерывание по уровню, если флаг постоянно сбрасывается.
GetSmart
Nov 14 2006, 15:18
Прерывание по уровню вызывается мгновенно при присутствии активного внешнего сигнала и разрешённых глобальных прерываниях. Бит прерывания нигде не устанавливается, сам не сбрасывается и помогать ему в этом не надо.
Насчёт 1+1=0 прикольно :-)
Мне такое и в голову не приходило. Но скорее всего сделано не так. И программно такой бит не установить. Если кто проверет - сообщите. Самому интересно.
archi2000
Nov 14 2006, 15:29
Хочу такое запрограммировать - программный одновибратор 100 мсек.
Начало.
Внешние прерывания запрещаем в регистре GICR.
Разрешаем прерывания от таймеров.
Разрешаем прерывания глобально.
Задержка 100 мсек.
Разрешаем внешние прерывания.
Если за эти 100 мсек внешие события были, то флаги int0 и int1 должны присутствовать и добавляем в теле прерывания к переменной единичку.
Запрещаем внешние прерывания.
Выполняем несколько комманд основной программы с проверкой различных условий.
Переходим на начало.
Так как в даташите написано, что флаг постоянно сбрасывается если прерывание по уровню, а я не хочу мгновенно это событие обрабатывать, то вот и не знаю будет ли этот алгоритм работать.
Где еще прочитать или ставить эксперименты?
GetSmart
Nov 14 2006, 16:16
Инициализируете нужное прерывание по фронту (или спаду, как надо). После очередного разрешения внешнего прерывания анализируете вручную вход INTx. Если он в нужной полярности - запоминаете где-нибудь. Всё это можно делать прямо из прерывания по таймеру - два раза подряд на включение и выключение анализа входов внешних прерываний. GICR по-моему лучше вообще не трогать. Лучше в этом регистре сразу выключить оба прерывания, а их настроить на нужный фронт. А потом только анализировать вручную вход INTx и его "захваченный" флаг прерывания. Сам так не делал, но думаю это сработает. Загрузка процессора - минимальная.
Забыл ещё кое-что. Перед "ручным" анализом входа INTx нужно сбрасывать флаг INTFx. А через 100 мс его только считывать и можно не сбрасывать.
Цитата(GetSmart @ Nov 14 2006, 18:18)

Насчёт 1+1=0 прикольно :-)
Мне такое и в голову не приходило. Но скорее всего сделано не так. И программно такой бит не установить. Если кто проверет - сообщите. Самому интересно.
Конечно не установить. А сбрасывать записью 1 - это чтобы при сбросе сбросить только нужные флаги.
Цитата(GetSmart @ Nov 14 2006, 18:18)

Насчёт 1+1=0 прикольно :-)
Мне такое и в голову не приходило. Но скорее всего сделано не так.
Именно так и сделано. Для проверки можете разрешить какое-нибудь прерывание при взведенном флаге этого прерывания - незамедлительно отправитесь по соответствующему вектору

.
Цитата
И программно такой бит не установить. Если кто проверет - сообщите. Самому интересно.
Сам бит прерывания программно не установить. Тем не менее (из даташита на mega48, в остальных аналогично):
Цитата
The External Interrupts are triggered by the INT0 and INT1 pins or any of the PCINT23..0 pins.
Observe that, if enabled, the interrupts will trigger even if the INT0 and INT1 or PCINT23..0 pins
are configured as outputs. This feature provides a way of generating a software interrupt.
GetSmart
Nov 14 2006, 18:54
Цитата(xemul)
Цитата
The external interrupts are triggered by the INT0, and INT1 pins. Observe that, if
enabled, the interrupts will trigger even if the INT0..1 pins are configured as outputs.
This feature provides a way of generating a software interrupt.
Тут немного о другом написано. Написано что для софтовых прерываний нужно сконфигурить нужный вход прерывания как выход и установив на нём нужный сигнал вызвать прерывание. К битам INTFx это отношение не имеет. А жаль. Лучше бы софтовые прерывания вызывать менее извратно, например как в LPC-армах.
Diusha
Nov 15 2006, 04:23
«А жаль. Лучше бы софтовые прерывания вызывать менее извратно, например как в LPC-армах.»
А зачем? Разве трудно в прогу всавить rcall Int_SubRoutine?
Цитата(GetSmart @ Nov 14 2006, 21:54)

Цитата(xemul)
Цитата
The external interrupts are triggered by the INT0, and INT1 pins. Observe that, if
enabled, the interrupts will trigger even if the INT0..1 pins are configured as outputs.
This feature provides a way of generating a software interrupt.
Тут немного о другом написано. Написано что для софтовых прерываний нужно сконфигурить нужный вход прерывания как выход и установив на нём нужный сигнал вызвать прерывание. К битам INTFx это отношение не имеет. А жаль. Лучше бы софтовые прерывания вызывать менее извратно, например как в LPC-армах.
Ну, вот и приехали!!! Как раз все наоборот. Тут же ясно все написано. Внешние прерывания могут возникать и тогда, когда порты ВВ установлены на
вывод. Но если прерывания возникли, то соответствующие флаги INTFx будут устанавливаться. Посмотрите схему конфигурации портов в DS внимательней.
Изменяя в программе значения на выходных портах (1->0 или 0->) Вы сможете вызывать прерывания в нужный момент времени. Но, еще раз повторюсь, external interrupts возникают при изменении значения на входе пина,
независимо от того, как сконфигурирован порт, на ввод или на вывод.
IgorKossak
Nov 15 2006, 07:36
Цитата(GetSmart @ Nov 14 2006, 20:54)

Цитата(xemul)
Цитата
The external interrupts are triggered by the INT0, and INT1 pins. Observe that, if
enabled, the interrupts will trigger even if the INT0..1 pins are configured as outputs.
This feature provides a way of generating a software interrupt.
Тут немного о другом написано. Написано что для софтовых прерываний
нужно сконфигурить нужный вход прерывания как выход и установив на нём нужный сигнал вызвать прерывание. К битам INTFx это отношение не имеет. А жаль. Лучше бы софтовые прерывания вызывать менее извратно, например как в LPC-армах.
even if переводится как "даже если", а вовсе не как "нужно".
Смысл от этого меняется кардинально.
Что же касается софтовых прерываний, то их в AVR нет вообще если никак не трогать периферию.
Согласен, что в некоторых ARM (да и других контроллерах) этот вопрос решён лучше.
Цитата(Diusha @ Nov 15 2006, 06:23)

А зачем? Разве трудно в прогу всавить rcall Int_SubRoutine?
При обычном вызове процедуры прерывания, т. е. собственно через прерывание, а не через call, прерывания запрещаются.
Этого нет при вызове через call. Запрещать прерывания придётся вручную до вызова.
GetSmart
Nov 15 2006, 09:25
Ну все тут прямо знатоки аглицкого как я погляжу. Только за смыслом беседы так же дотошно почему-то не следят. Смысл от "даже если" к "нужно" смещается очень легко. Нужно всего лишь прочитать все предложения в обратном порядке. Начиная с софтверных прерываний (о которых и шла речь) и доходя до того как их организовать.
Вопрос-то был всего-лишь в том, как аппаратно реализованы биты INTFx и можно ли их "вручную" установить для вызова софт-прерывания. Ну и кроме этого, какие ещё механизмы влияют на изменение этих флагов. Хотя главный вопрос - вопрос автора, как ему сделать то что нужно.
Dog Pawlowa
Nov 15 2006, 11:27
Как по мне, то любая неочевидная логика работы устройства, отличающаяся от if ... then ..., затрудняет даже собственное понимание после недели отвлечения на другой проект. Маскирование прерывания, чтобы не обработать прерывание от помех - это заботливо поставленные в собственном сарае грабли. Так можно делать, пока проект помещается на страницу текста и в голову. У меня в среднем проекте 15-20 файлов.
Вывод. Прерывания не маскировать, но при обработке его предусмотреть очевидный механизм анализа.
SasaVitebsk
Nov 15 2006, 16:57
Цитата(archi2000 @ Nov 14 2006, 18:29)

Хочу такое запрограммировать - программный одновибратор 100 мсек.
Начало.
Внешние прерывания запрещаем в регистре GICR.
Разрешаем прерывания от таймеров.
Разрешаем прерывания глобально.
Задержка 100 мсек.
Разрешаем внешние прерывания.
Если за эти 100 мсек внешие события были, то флаги int0 и int1 должны присутствовать и добавляем в теле прерывания к переменной единичку.
Запрещаем внешние прерывания.
Выполняем несколько комманд основной программы с проверкой различных условий.
Переходим на начало.
Так как в даташите написано, что флаг постоянно сбрасывается если прерывание по уровню, а я не хочу мгновенно это событие обрабатывать, то вот и не знаю будет ли этот алгоритм работать.
Где еще прочитать или ставить эксперименты?
Я не вижу проблем в Вашем алгоритме, но боюсь что не совсем понимаю его. Вы лучше опишите что хотите сделать, а мы предложим Вам варианты.
Можно в прерывании смотреть фронт а можно, например каждый раз менять фронт и по разному обрабатывать. Можно отложить обработку прерывания, только надо учесть, что при запрете прерывания флаг выставится только один раз. Остальные будут потеряны. Лучше, как предлагает, Dog Pawlowa прерывания обрабатывать всегда. А если Вы не хочете увеличивать объём вычислений в прерывании, то в прерывании только сохранять очередь. А обрабатывать эту очередь в голове.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.