Запретить прерывание внутри функции обработки прерывания?
- Войдите на сайт для отправки комментариев
Чт, 09/05/2013 - 11:38
Есть некоторая система, построена на mega
Есть два обработчика прерывания - один работает по таймеру, второй - "слушает" пин.
Оба прерывания нужны, оба прерывания важны.
Первое прерывание используется для "графики", второе - для приема данных по радиоканалу.
Сейчас работает, но, когда приходит радиосигнал - есть нарушения в графике (помаргивания и т.п.) - очевидно, что во время отработки прерывания по таймеру возникло аппаратное прерывание и это нарушило "тайминги" и динамическая индикация отрабатывает с косяками.
Попробовал сделать так:
ISR(TIMER1_COMPA_vect) { noInterrupts(); // .............. // что-то тут делаем // .............. interrupts(); }
Не сработало - вижу те же "помаргивания". Как обойти?
Лучше откладывать обработку, а не запрещать - тогда контролируешь ситуацию, можешь отложить обработку.
Используя флаги активности прерываний, в каждом обработчике знаешь активно ли другое, и просто делаешь выход. Вряд ли это поможет от дерганий.
Но с графикой ты попал, попробуй посчитать частоты расвертки. Может выйдешь на 21-ый кадр 8=) Глаз вещь темная, исследованию не подлежит. Порой такое увидишь!
А на графику лучше отдельный камень иметь, во!
при выполнении любого прерывания, все остальные автоматически отключаются. даже если оно и произойдет внутри другого, то поставиться лишь флаг в соотв. регистре. а уже после выхода из прерывания, провериться флаг и выполниться (если было несколько разных прерываний, то все, согласно векторов). можете попробовать разве что сбросить флаг другого прерывания. как правило сброс осуществляется записью единицы, т.е. флаг наличия прерывания единица, для сброса в эту единицу надо записать единицу.
флаг регистров внешних прерываний называется EIFR. пишите в него просто 0xFF и пробуйте.
Скорей всего внешнее прерывание, которое обрабатывает прием данных по радио каналу, выполняется слишком долго. Как уже выше писали, при выполнении одного обработчика прерывания все остальные запрещаются. Вот поэтому динамическая индикация и подвисает во время приема данных. Что делать? Уменьшать время выполнения обработчика на прием данных.
__Alexander, спасибо! Попробую.
Проблема, похоже, как раз в том, что при работе внешнего прерывания "смещается" по времени исполнение прерывания по таймеру, что и приводит к "визуальным эффектам".
Evgen, да, похоже так и есть, но тут я упираюсь работу с модулем nrf24l01 - и ускорить получение данных от него я не могу :(
флаг регистров внешних прерываний называется EIFR. пишите в него просто 0xFF и пробуйте.
Не помогло... может, лучше будет проделать аналогичную манипуляцию с флагом прерывания по таймеру? __Alexander, подскажите, какой это флаг?
Почему не происходит выполнение кода в loop ?
А где INPUT_PULLUP или INPUT? И опять Вы забыли про volatile и ATOMIC_BLOCK.
А что это за процесс? Чему равна частота?
А где INPUT_PULLUP или INPUT? И опять Вы забыли про volatile и ATOMIC_BLOCK.
Про volatile поняла. Будет volatile bool FlagOtscheta=false;
INPUT_PULLUP мне не нужно наверное, так как у меня есть внешний подтягивающий резистор.
Про ATOMIC_BLOCK не знаю ничего.
Как я понимаю, все дело в таймере....?
Вспомните свой вопрос про тахометр. Там и тема ATOMIC и volatile для long переменных были разобраны.
Разобралась....
Так правильно будет?
Формально - правильно, но избыточно и не сильно надежно.
millis() в ISR не тикает - это верно. Но это не может помешать считать в обработчике его последнее значение для того, чтобы понять, на какой миллисекунде прервался ход выполнения основного цикла.
Вроде правильно таймер работает, во время выключается
До тех пор, пока ISR на середине блокирующей функции не будет вызван. Тогда ваша релюшка будет клацать с отставанием. Найдите тему про тахометр, не ленитесь.
Вот так?))
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Компилится, но не заливал на железо. ATOMIC_BLOCK внутри себя блокирует прерывания, так что не надо совать туда всё подряд.
Спасибо. Буду изучать.
Еще вопрос. Подскажите как осуществить следующий алгоритм:
При включении выключателя лампочка загорается, при выключении включается реле на 3 секунды, по истечению этого времени оно выключается. Далее мне нужно чтобы действия повторялись...т.е. при включении загоралась, при выключении включалось реле...и т.д....В какой момент FlagOnf мне нужно вернуть в false...никак я не соображу.
https://youtu.be/jAFOeNKw3ww
А так же:
Можно ли использовать два раных условия в прерываниях?
А так же:
Можно ли использовать два раных условия в прерываниях?
Большое Спасибо
Частично не в тему...
При включении зажигания и последующем выключении, при соблюдении ряда условий, включается реле и зажигание продолжает работать X секунд затем выклчюается.
Переход на пине D2 с LOW на HIGH отслеживаю attachInterrupt(0,bos,RISING);
На реальном замке зажигания не пробовала, но существует мнение, что будут ложные срабатывания при повороте ключа в положение старта, дребезг. Так?
Как бороться?
Непременно будут. Особенно на прерывании ))
Ставьте или какой-нить триггер Шмитта или делайте программный антидребезг (без прерываний). Хотя, наверное, если через оптопару-резистор заводит - это несколько подправит ситуацию. Впрочем, я тоже с интересом почитаю, что Вам умные люди посоветуют.
Дело еще в том, чтобы для машины это переключение было незаметным, чтобы она продолжала работать, так что задержка на проверку дребезга нужна минимальная.
Как то так...только, как указано выше, избыточно...)
Для такой задачи вам не нужны прерывания. Простой дижиталрид с перепроверкой через 10мс закроет вопрос более, чем полностью.
Так мне нужно чтобы задача выполнялась только после того, как зажигание было включено, а затем выключено
Без разницы. Прерывание тут - оверкилл.
Частично не в тему...
При включении зажигания и последующем выключении, при соблюдении ряда условий, включается реле и зажигание продолжает работать X секунд затем выклчюается.
Переход на пине D2 с LOW на HIGH отслеживаю attachInterrupt(0,bos,RISING);
На реальном замке зажигания не пробовала, но существует мнение, что будут ложные срабатывания при повороте ключа в положение старта, дребезг. Так?
Как бороться?
Эмм... а в чем смысл применения оптрона без гальванической развязки входа и выхода? чем полученный трёхполюсник лучше одинокого транзистора?
Без прерывания
Или так, места занимает меньше:
delay() можете сами поменять на неблокирующий код. Я там дырки в нумерации шагов оставил.
Не работает. Но смысл я поняла. Спасибо.
Несколько вопросов:
Стоит ли избавляться от паузы 100 мс, или она не столь значительна?
Почему Вы пишите
if
(HIGH == digitalRead(2)) {, а не
if
(DigitalRead(2)) {
Для наглядности или что-то иное?
Несколько вопросов:
Стоит ли избавляться от паузы 100 мс, или она не столь значительна?
Почему Вы пишите
if
(HIGH == digitalRead(2)) {, а не
if
(DigitalRead(2)) {
Для наглядности или что-то иное?
Не работает, потому что в case 0x00 нет выпрыгивания на case 0x01 через systemState. Прошляпил-с. С case просто наглядней переходы в состояния. Через месяцок вы на свои if-ы будете смотреть и думать - как же тут флаги перекидываются...
От паузы избавляться не стоит - она же дает время успокоиться дребезжащим контактам. Но переписать на по типу blink без delay стоит. Если, конечно, предполагается что-то еще вне свича делать постоянно.
Пишу для выработки привычки. На if(variable = LOW) компилятор не обругается, а вот на if(LOW = variable) - обматерится. В обоих случая выражение записано неверно с точки зрения использования оператора сравнения. Дешевый способ обнаружить, где затупил или закопипастил неверно.
while (true) в лупе исключительно с целью не связываться с глобальными/статическими переменными. Ну и немного ускорить цикл (на копейки), выкинув то, что за пределами лупа используется. В вашем случае конструкция применена бессмысленно.
Спасибо.
Не работает, потому что в case 0x00 нет выпрыгивания на case 0x01 через systemState. Прошляпил-с. С case просто наглядней переходы в состояния. Через месяцок вы на свои if-ы будете смотреть и думать - как же тут флаги перекидываются...
А еще не 0x06, а 0x05 =)))))))