Длительность функции в прерывании

Modsley
Offline
Зарегистрирован: 14.01.2018

Приветствую.

Везде пишут "Делайте обработчик прерывания как можно короче, чтобы код успел выполниться за время прерывания"

Отсюда вопрос. 

А как понять, успевает написанная мной функция выполниться или нет?

Например, функция делает какие-то арифметические вычисления. Как понять, доделала она их до конца или на полпути интервал прерывания закончился?

nik182
Offline
Зарегистрирован: 04.05.2015

Интервал прерывания не может закончится. Пока не выполнена команда выхода из прерывания. Если за это время случится другое прерывание, то оно будет выполнятся сразу после выхода из текущего прерывания. А вот если за это время случится больше чем одно то же самое прерывание, то второе и последующие будут потеряны. Легко проверяется потерей значений micros() если внутри прерывания устроить задержку более 8 мкс.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Modsley пишет:

Как понять, доделала она их до конца или на полпути интервал прерывания закончился?

Что Вы понимаете под интервалом прерывания? Обрабатчик прерывания может выполняться сколь угодно долго. Проблема в том, в это время не буду обрабатываться новые прерывания. Вас интересует не прилетело ли новое пока Вы выполнялись? Так проверьте флаг прерывания после того, как закончили вычисления, и если взведён, то включите какой-нибудь светодиод.

Modsley
Offline
Зарегистрирован: 14.01.2018

Ааааа, эвона... А я-то, тундра, думал, что у прерывания есть конечная длительность, за которую код должен выполниться. 

Спасибо.

Как я понимаю, глобальные переменные, в которые обработчик прерываний будет что-то писать, чтобы это было доступно в других местах программы, нужно определять как volatile?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ага. Можно, конечно, и не определать, если хотите чтобы жизнь была весёлой и менее предсказуемой.

sva_khv
Offline
Зарегистрирован: 19.12.2016

Modsley пишет:

Ааааа, эвона... А я-то, тундра, думал, что у прерывания есть конечная длительность, за которую код должен выполниться. 

Для понимания совета почему код функции вызываемый при прерывании должен выполняться как можно быстрее.

Выполнение основного кода программы - это ваши повседневные действия (сон, туалет, еда, работа, вождение машины и т.д.) А прерывание - это звонок от жены с инструкциями что надо купить/сделать.

На звонок вы отвечаете в обязательном порядке чем бы не занимались. И пока получаете команды от жены - ничего не далете, ни на что не реагируете. Если сидите на горшке или чистити зубы - ерунда, если на работе на совещении - ну выпадете из реальности на пару минут - терпимо. А если за рулем или разговариваете с начальником? А жена при этом любит подробно объяснять минут по 5 каждую задачу? Последствия понятны?

В этом примере лучше по тел получить СМС списов продуктов, а за покупками идти в основной программе. Неправильно - в функции прерывания получить список продуктов и идти в магазин и пока не купишь все продукты - из функции прерывания не возращаться. 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

sva_khv пишет:

В этом примере лучше по тел получить СМС списов продуктов, а за покупками идти в основной программе. Неправильно - в функции прерывания получить список продуктов и идти в магазин и пока не купишь все продукты - из функции прерывания не возращаться. 

Если идти дальше, лучше отследить факт получения СМС, а в основной программе разбираться, от кого СМС, надо не надо, список не список.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Абычна, в прерывании просто взводится флаг, что что-то надо обработать.  А в основной программе потом, видя, что кто-то флагом размахивает, не спеша, берешь ииии....

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

DetSimen пишет:

Абычна, в прерывании просто взводится флаг, что что-то надо обработать.  А в основной программе потом, видя, что кто-то флагом размахивает, не спеша, берешь ииии....

- мертвец перед смертью махал флагом.
- чего хотел?
- а, не пофиг уже?
Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Да можно и прерывания обрабатывать достаточно долго. Просто делать это надо грамотно, разрешая другие прерывания и функция обработчика может быть реентерабельной, то есть позволять обрабатывать повторно пришедшее то же самое прерывание. Не так оно уж и ложно. Все советы по краткости обработчика - это расчет на полуграмотного погромиста, который плохо понимает чего делает его программа или тупо пользует стыренный код или т.н. "библиотеки".

Да и "читаемость" кода - это поперечное явление.

ssss
Offline
Зарегистрирован: 01.07.2016

Arhat109-2 пишет:

Все советы по краткости обработчика - это расчет на полуграмотного погромиста, который плохо понимает чего делает его программа или тупо пользует стыренный код или т.н. "библиотеки".

А нифига... Это жалкое наследие первых допотопных МК типа ПЫХ-АВР с убитой системой прерываний и недоразвитым железом и первых ПСюков... где пока "форматируется дискета" система в ступоре...

Сейчас на новых копеечных МК на всю эту краткость можно забить... с лёгкостью... ввиду наличия развитой многоуровневой системы прерываний и развитого железа...

На МК выкручивались при помощи ОСь... На особо слабых МК юзали ОСь типа ОСА... Ну или извращались без ОСи... кто как мог и кто на что учился... гранича порой с умопомешательством...

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже ssss "пернул" не проснувшись. при прерывании регистры и адресс на котором был процессор сохраняются в память. И если вы пытаетесь организовать прерывание в прерывании и так много раз , то у вас память тратится на сохранение. Ну и время на операции сохранения. Так что все же лучше обработчики прерываний делать короткими. 

ssss
Offline
Зарегистрирован: 01.07.2016

qwone пишет:

И если вы пытаетесь организовать прерывание в прерывании и так много раз , то у вас память тратится на сохранение.

Ы что??? )))))))))))))

В новых МК сохранение контекста хардварное... ))))))))))))

Цитата:

Ну и время на операции сохранения.

Бред... На новых МК юзают такую фишку... чтобы уменьшить время входа в прерывание... внимание!!!... входят в прерывание... а уж из него вызывают другие прерывания... не выходя из первого... )))))))))))))))))

Цитата:

Так что все же лучше обработчики прерываний делать короткими. 

Бред... Насколько короткими... и для чего??? Может в прерывании ваще запретить что-то делать??? ))))))))))))))

В старых и допотопных МК - да... там по другому никак... жалкое наследие прошлого...

А в новых...

Если есть приоритеты прерываний... если есть вытесняющие прерывания... то почему их не использовать... ась??? ))))))))))))))))))

Ну и пофигу... что луп майна может быть пустым... Вас это сильно парит... до "аж кушать не могу"??? ))))))))))))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone, прекращайте кормить тролля, оптяь ведь начнётся сейчас.

sva_khv
Offline
Зарегистрирован: 19.12.2016

xDriver пишет:

Если идти дальше, лучше отследить факт получения СМС, а в основной программе разбираться, от кого СМС, надо не надо, список не список.

Согласен, можно и так.

Реальный пример - счетчик гейгера. Импульс - прерывание - увеличивыем переменную на 1 - выход из прерывания. А уж в основной программе разбираемся как импульсы пересчитать в зиверты, отмеряем период счета, решаем когда обнулять переменую.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016
void  detect_hol() {    // обработка внешнего прерывания на пересекание нуля снизу от датчика холла
 realTime_hol =  micros();// читаем в переменную время входа в прерывание
 if(realTime_hol < prevTime_hol) // если время обнулилось то
  {
  prevTime_hol = realTime_hol;  // запишем реальное время в переменную (для следующего входа в рерывание) а расчет между импульсами оставим как и был  
  }
  else// если реальное время больше прошлого времени то
  {
    valTime_hol = realTime_hol - prevTime_hol ;// посчитаем разницу между импульсами от датчика холла
    prevTime_hol = realTime_hol;  //  запишем реальное время в переменную для следующего входа в функцию прерывания
  }
}

что скажете про мою функцию прерывания, это долго будет выполняться , и можно ли ее укоротить?

sadman41
Offline
Зарегистрирован: 19.10.2016

Коль скоро вы своими переменными не пользуетесь в прерывании для активных действий, а иное нам неизвестно, в обработчике вполне можно оставить только realTime_hol =  micros();

OlegK
OlegK аватар
Offline
Зарегистрирован: 26.11.2014

Baks пишет:
и можно ли ее укоротить?

Ну выше предлагалось -

void  detect_hol() {    // обработка внешнего прерывания на пересекание нуля снизу от датчика холла
 realTime_hol =  micros();// читаем в переменную время входа в прерывание
 flag = true;
}

loop() {
  if (flag) {
          if(realTime_hol < prevTime_hol)  {
                 prevTime_hol = realTime_hol;
          } else {
                valTime_hol = realTime_hol - prevTime_hol ;
                prevTime_hol = realTime_hol;
          }
    flag = !flag;
    }
}

и тут можно чуть упростить -

loop() {
  if (flag) {
     if (realTime_hol > prevTime_hol)  {
         valTime_hol = realTime_hol - prevTime_hol ;
     } 
     prevTime_hol = realTime_hol;
    flag = !flag;
    }
}
Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

да спасибо, все понял, единственное я преживаю контроллер успвал обрабатывать все прерывания, у меня получается движок с 15 000 оборотами в минуту, а на 1 оборот вала приходится 4 прерывания, и того 60 000 прерываний по датчику холла.

плюс детектор перехода через поль на вход и на выход ( частота выходит 100 герц)

и третье прерывание по таймеру. срабатывают каждые 40 мкс после выхода полуволны из нуля?

не получится ли у меня сплошные прерывания а в основной код будет заходить по выходным ?)))

хватит ли шустрости микроконтроллеру, или стоит пересмотреть всю реализацию кода?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Замерьте.

GarryC
Offline
Зарегистрирован: 08.08.2016

Позволю себе заметить, что прежде, чем использовать прерывания (или не использовать) необходимо уточнить задачу.
Например, у Вас имеется 60000 срабатываний датчика Хола в минуту, это 1000 в секунду или период 1мс. Вроде бы переывания вполне смогут обработать такой поток, но нужно ли это Вам?
Возможно, Вам просто нужно дождаться определенного количества импульсов для того, чтобы привод встал в определенное положение. Тогда вполне можно завести импульсы на аппаратный счетчик (они есть в Ардуино) и ждать прерывания (но уже не от каждого импудьса), которое возникнет, когда счетчик досчитает до конкретного (заранее определенного) значения.
А может, Вам просто нужно знать, что привод крутится и тогда опять счетчик Вам поможет.

И для срабатывания через 40 мксек после полуволны совершенно не обязательно дергать процессор, а можно заппрограммировать в таймере изменение уровня после прихода входного сигнала.

В общем, "независимая от ядра периферия" Вам в помощь.

sva_khv
Offline
Зарегистрирован: 19.12.2016

GarryC пишет:

 Тогда вполне можно завести импульсы на аппаратный счетчик (они есть в Ардуино) ...

А можно поподробней  про апаратный счетчик? Или что прочитать об этом? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Даташит читайте. Таймер можно сконфигурировать, чтобы считал внешние импульсы.

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

попалась статья, можно почитать по русски )))https://sites.google.com/site/vanyambauseslinux/arduino/tajmery-sceetciki-arduino

а в низу статьи еще ссылка интересная 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Baks пишет:

попалась статья, можно почитать по русски )))https://sites.google.com/site/vanyambauseslinux/arduino/tajmery-sceetciki-arduino

а в низу статьи еще ссылка интересная 

Во втором абзаце обнаружил:

Микроконтроллер Arduino оснащён трёмя таймерами-счётчиками с номерами 0, 1 и 2.

Видимо, автор никогда не читал этого: http://arduino.ru/Hardware

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

наткнулся на один пост, и почитал что можно сделать счетчик импульсов по совпадению.

http://arduino.ru/forum/apparatnye-voprosy/timer1-dlya-podscheta-vneshnikh-impulsov

и все таки я решил попробовать запихать все в обычные прерывания, так как получается на прерываниях 1100 герцовое прерывание (холл 1000 + в сети 220в- 100 прерваний на спаде и на подьеме полуволны), и это максимум, на максимальных оборотах движка.

а от третьего таймера прерываний я решил вообще отказаться, буду высчитывать микросы в основном цыкле.

в общем еще чутьчуть и попробую что полчится....