С чего бы вот такой код в прерывании не работает (при обычном вызове работает)
- Войдите на сайт для отправки комментариев
Пнд, 15/07/2013 - 12:13
Собственно есть работающий код, решил его в прерывание засунуть и он почему то перестал работать, ловит максимум один имульс. Доходит до условия if(PreamblePulseCount != 12){return;} только с одним импульсом
int duration[12]; byte PreamblePulseCount; int rs = digitalRead(HCS_RECIEVER_PIN); if(rs == 0){ return; } // что то поймали, будем анализировать unsigned long TimeStartReading = micros(); unsigned long PulseStart = TimeStartReading; unsigned long curpoz = TimeStartReading; int stat = 1; int tdur = 0; PreamblePulseCount = 0; int i,j; // ловим преамбулу ////////////////////////////////////////////////////////////////////// // Преамбула состоит из 12 импульсов, типичная длительность 9200 мкс // Длительность преамбулы 23 базовых импульсов Те, типичный импульс Те 400 мкс while((curpoz - TimeStartReading) < 20000){ rs = digitalRead(HCS_RECIEVER_PIN); if (stat != rs) { // состояние изменилось if(stat == 1 && rs == 0){ // окончание импульса tdur = curpoz - PulseStart; if(tdur < 300 || tdur > 600){ break; } duration[PreamblePulseCount] = tdur; PreamblePulseCount ++; stat = 0; if(PreamblePulseCount == 12){ break; } } else { // начало импульса stat = 1; PulseStart = curpoz; } } curpoz = micros(); } if(PreamblePulseCount != 12){ return; }
С того что, возможно, невнимательно читали attachInterrupt(interrupt, function, mode) | Аппаратная платформа Arduino
раздел "замечание по использованию".
Там упоминается millis(), но к micros() - это тоже относится (вообщем к любым функциям времени). ВОзможно еще что-то нарушили (код не целиком дали, поэтому этого не видно, как вы объявляли переменные и т.п.).
И вообще - идея делать while(как-то-длинное-условие) - внутри обработчика прерывание - это "фу, фу, фу..."
Ваша задача - "словили прерывание", сделать там "минимально необходимую работу" (прочитать время, состояния входов...) и как можно быстрее выйти из обработчика. Все "теждолое-вычислительное-ожидательное" - должно быть в loop(). Обработчик это "внештатная ситуация". Когда процессор "отвлекли от основных задач..." Поэтому нужно "не на долго отвлекать..."
Читал то как раз внимательно и поскольку micros() там не упоминается рассчитывал, что его применять можно. Тем более, что прошелся поиском и вроде народ micros() применяет..
Если все таки нельзя, то конечно понятно, почему не работает. Спасибо
Да, не очень красиво. Но процесс идет слишком быстро, пришлось например минимизировать вызовы micros() чтобы вписаться по времени. Лишний вызов функции сбивал чтение, т.к. происходил слишком долго по сравнению с длительностью сигнала
Вообще конечно буду переписывать
Читал то как раз внимательно и поскольку micros() там не упоминается рассчитывал, что его применять можно. Тем более, что прошелся поиском и вроде народ micros() применяет..
Ну все функции перечислить не возможно.... главное суть понять. Когда у вас сработал обработчик прерывания и вызвалась ваша функция "обработки прерываний" - в этот момент все остальные прерывания (внешние, прерывания таймера, прихода данных по Serial и т.п.) - запрещены. не могут сработать.
Следовальное "часы стоят", "серил не слушаем", прерывание на другом пине - поймать не можем..... и т.п.
Глючат и все функции которые зависят от этого delay (так как он использует внутри millis()) и т.д. и т.п.
Поэтому и важно - как можно раньше выйти из функции обработчика. Это как-бы "аврал...", а находится в этом режиме долго - череповато.
В ваш код - сильно не вникал. Но.... Вот вещи типа "
if (stat != rs) { // состояние изменилось" - можно попытатся убрать. Понастраивать точнеие на что именно будет срабатывать прерывание. на CHANGE, на RAISE и т.п.
Возможно и необходимость чтения пина отпадет (если мы знаем, что прерывание срабатывает при переходе с LOW на HIGH, то зачем читать пин? И так знаем что он HIGH)
Серию импульсов считать нужно?
Ну так просто заведите какой-то счетчик cnt++
И когда он будет cnt>12 - выполняйте что-вам-там нужно....
Вообщем - тупо "скопировать" логику с loop в прерывания - не выйдет. Нужно переписавать/передумывать алгоритм под "прерывестый поток исполнения", а не "непрерывный".
Это я уже понял :-)
Да, буду переписывать на логику прерываний, прерывание типа CHANGE и по нему ловить фронт/конец импульса