PCINTx обработчик прерываний
- Войдите на сайт для отправки комментариев
Чт, 19/07/2012 - 22:30
Добрый вечер!
Подскажите пожалуйста - как выделить pin, который сработал по прерыванию PCINTx.
Добрый вечер!
Подскажите пожалуйста - как выделить pin, который сработал по прерыванию PCINTx.
Его нельзя выделить, но его можно назначить регистром PCMSKx.
Вот тут обсуждалось: arduino.ru/forum/programmirovanie/dopolnitelnye-vneshnie-preryvaniya
Добрый вечер!
Подскажите пожалуйста - как выделить pin, который сработал по прерыванию PCINTx.
Запоминать состояния пинов при каждой сработке. При каждой сработке сравнивать "с предыдущем состоянием". Кто "не совпадает", тот и "сработал."
Запоминать состояния пинов при каждой сработке. При каждой сработке сравнивать "с предыдущем состоянием". Кто "не совпадает", тот и "сработал."
Да, но при таком способе регистрация происходит как на передний фронт, так и на задний....
на данный момент я реализовал так:
Импульс имеет отрицательную форму. Может это можно упростить или улучшить?
Запоминать состояния пинов при каждой сработке. При каждой сработке сравнивать "с предыдущем состоянием". Кто "не совпадает", тот и "сработал."
Да, но при таком способе регистрация происходит как на передний фронт, так и на задний....
Ну? И что мы никак не сможем отличить фронт от бека?
Вот смотрите. Я вам говорю "кто-то только что включил или выключил свет в комнате". Но я не знаю он включил или выключил. Глядя на лампочку (или положение выключателя) вы можете ответить что именно он сделал? Включил или выключил?
Вот так же и с пином. Вы знаете что "пин поменял значение", можете узнать его текущие состояние, в чем проблема понять по какому фронту он изменился?
Или, если вы все-таки реализуете хранение предыдущего состояния. У вас есть всего четыре комбинации "прошлое-новое" состояние. Которые спокойно можно интерперитировать (даю в паре старой-новое-что-назнчит).
на данный момент я реализовал так:
Тут можно было-бы понудить по поводу стилистики кода и его переносимости, но не вижу смысла (это уже после того как код заработает). А пока нет главного - хранения предыдущего состояния. Значит в общем случае узнать какой именно пин поменялся - вы не можете.
Вот весь код
Вы бы как-то прокомментировали свой "вот весь код". Что это? "Вот зацените работающий код" или "вот попробовал так, но не работает" (тогда в чем проявляется)?
На первый взгляд код "странен". Но может быть и работающий (смотря что вы хотели от него добится).
По крайней мере с изначальной задачей "узнать какой пин сработал" - IMHO коррелирует слабо. Сравнений с "прошлым состоянием" так нигде и не наблюдается (хотя вроде была попытка запоминать его, изощренная ;) ). Обрабатываются какие-то случаи когда сразу пара пинов установленна в HIGH (строки 14 и 24) - чего в изначальной задаче не упоминалась. Да и вкомментариях упоминается только два сенсора, а не четыре. Хотя подтяжку, опять-таки, включаете для 4-рех.
Зачем-то, в строке 31, включили два пина на выход.
И еще. Вы сделали попытку запоминать (и даже вести историю, не знаю зачем) "прошлого состояния пина". Возможно будет проще запоминать "прошлое состояние порта", целиком, а уж из него получать "прошлое состояние пина" (какого нужно).
Прошу прощения, что не мог сразу указать конечную цель, так как ее даже не представлял (была только поставлена задача), поэтому задавал вопросы и решал их по мере поступления. Сообственно суть в том, что есть две цифровые клавиатуры передающие код в формате wiegand8 (т.е. на одну используется три провода D0, D1 и земля). В состоянии покоя на D0 и D1 присутствует логическая единица, как только на клавиатуре нажата цифра передается пакет из 8 бит, где "0" передаются по D0, а "1" по D1. Задача была выводить эти цифры на LCD(вывод пока не реализован), а проблема в том, что документации на них нет - соответственно формат и последовательность тоже была неизвестна.
Два пина на выход, это светодиод и реле, но в коде я пока до них еще не дошел...
Если запоминать состояние порта целиком, то потом придется все равно делить на два дисплея каждую клавиатуру...
Еще раз прошу прощения....
Код работает - большое спасибо!!!
wiegand8 (т.е. на одну используется три провода D0, D1 и земля). В состоянии покоя на D0 и D1 присутствует логическая единица, как только на клавиатуре нажата цифра передается пакет из 8 бит, где "0" передаются по D0, а "1" по D1.
Честно говоря не слышал про такую шину. Да и утвреждение "0 передается по D0" , а "1 по D1" вызвает какое-то непонятный зуд можжечка. Никогда не слышал про передечу 0 и 1 по разным проводам. Да и не понимаю зачем такое могло понадобится.
А вот если предположить что одна из них - линия данных (и нули и единицы по ней гонятся), а падение второй в ноль означает "читай новый бит с линии данных" (то есть - тактируюуща), то шина сразу становится подозрительно похожа на SPI (или другой какого родственика). И тогда можно не мудрится с прерываниями, а попробовать воспользоваться аппаратным SPI, и весь байт принимать одним простым read()
Подробнее по формату здесь ru.wikipedia.org/wiki/Виганд_(интерфейс)
Проблема в том. что каждый производитель для определения номера может использовать разную последовательность бит, например цифра один может быть у одного производителя 00000010 или 01000000 у другого. И еще обычно один бит из 8 используется для проверки четности/нечетности.
Кстати я вместо клавиатуры подключил считыватель с форматом Wiegand26 в условии заменил 8 на 26 и карточка доступа прочиталась нормально, отсюда возник следующий вопрос - как унифицировать код, чтобы можно было читать и wiegand8 и wiegand26 и wiegand32 и т.д.? Предполагаю замерять время между посылкой первого и второго бита в посылке, а потом по этому интервалу складывать биты до тех пор пока есть изменения в этом интервале.
Подробнее по формату здесь ru.wikipedia.org/wiki/Виганд_(интерфейс)
Век учись - дураком помрешь :) У меня, почему-то не вышло сходу нагуглить. Ценная, лично для меня, ветка получилась. Уже второй раз "что-то новое узнал" :)
Но, исходя из этого. Ваш код, скорее всего, все равно имеет "скрытую лажу". Все-таки запоминать прошлое состояние порта и выяснить "какой же именно пин" поменялся - все равно нужно.
Представте что у вас будет происходить если оба сенсора начнут передавать данные одновременно?
Придположим data1 первого упал в ноль. Вы, в первый сенсор записали 1. Но... если до того, как data1 вернется в логическую 1 у вас произойдет импульс на втором сенсоре, то есть обработчик вызовется еще раз - у вас опять произойдет чтение DATA1, и в первый сенсор попадет лишняя 1. А потом, кого отпустится DATA1 - произойдет "мусорное чтение" данных второго сенсора.
Проблема в том. что каждый производитель для определения номера может использовать разную последовательность
Хе-хе. Это вы еще с инфакрасными пультами не корячились. Ну, то есть, большинство-то, все-таки, попадают под тот или иной известный проктокол, но... не все. Причем там даже само кодирование может отличатся. У одних "смысл" несет длинна импульсов, у других - паузы между ними и т.п. Ну а содержимое кода - вообще полная анархия :)
wiegand8 и wiegand26 и wiegand32 и т.д.? Предполагаю замерять время между посылкой первого и второго бита в посылке, а потом по этому интервалу складывать биты до тех пор пока есть изменения в этом интервале.
Ну "направления правильное". Хотя ваша ссылка на вики, наталкивает на другой, хотя и родственный подход
Разделение кадров осуществляется по таймауту. Реально минимальное время между кадрами 0,5 сек., рекомендуемый таймаут для контроллера СКУД — 50…250мс.
То есть, определять "конец передачи" не условием "сколько бит приняли", а "по таймауту". В обработчике засекать время когда произошло изменения пина (и взводить какой-то флаг - "мы принимаем данные"). Если больше какой-то времени, при взведенном флаге, нет новых сработок - считать "код принятым",выводить его (возможно проверив четность), и сбрасывать флаг.
Но, исходя из этого. Ваш код, скорее всего, все равно имеет "скрытую лажу". Все-таки запоминать прошлое состояние порта и выяснить "какой же именно пин" поменялся - все равно нужно.
Представте что у вас будет происходить если оба сенсора начнут передавать данные одновременно?
Придположим data1 первого упал в ноль. Вы, в первый сенсор записали 1. Но... если до того, как data1 вернется в логическую 1 у вас произойдет импульс на втором сенсоре, то есть обработчик вызовется еще раз - у вас опять произойдет чтение DATA1, и в первый сенсор попадет лишняя 1. А потом, кого отпустится DATA1 - произойдет "мусорное чтение" данных второго сенсора.
Да, такой эффект есть - особенно при одинаковых комбинациях кода...надо подумать, как это более оптимально решить, ведь если я правильно понимаю процессор при работе на частоте 18МГц обрабатывает 18 миллионов команд, тогда за 40 микросекунд(длина импульса передачи бита) он обработает 720 простых команд, а если сложных, то можно и не уложиться?
Я не понимаю во что вы собрались "укладываться". Честно говоря - лень хмурить мозг. Тем более что "это тут ни причем". Проблема-то в "одновременности". А подход "будем верить что одновременно импульсы никогда не не совпадут" - изначально не правильный.
Я уж не знаю, в какой раз говорю: вам нужно запоминать состояние порта. Что сложно в том что-бы сделать prevPINB=PINB в конце обработчика? И, потом, сравнением "текущего" с "предыдущим" выяснять какой пин сработал. Не хотите сами это делать - в начале ветки вам давали ссылку где это уже обсуждалось. Там, вроде, есть и ссылочки на готовые библы.
> И, потом, сравнением "текущего" с "предыдущим"
Даже сравнивать, вообщем-то не нужно. Нужно провеить что "в старом пин был 1" (prevPINB), а в новом он "0" (PINB). В сообщении #4 я уже перебирал вам все комбинации "старого-нового" сотояния.
Тогда у вас корректно отрабает даже если оба датчика тикнуть "ну вообще синхронно". Даже когда сами импульсы не то что "наложатся примерно", а даже "начнутся" в один и тот же момент.
Вообщем примерно так (не запускал, но идея думаю понятна):
Вообщем примерно так (не запускал, но идея думаю понятна):
странно, при такой проверке вначале работало нормально, но потом произошел сдвиг и одна клавиатура начала добавлять ноль....
Нормальный код клавиатуры:01011101
Ненормальный:010111010
Интересно откуда он берется?
А еще раз через десять и вторая клавиатура стала добавлять ноль
Сделал вот так:
пока работает....
Сделал вот так:
пока работает....
Все равно сбивается - правда намного реже....после сбоя начинает выдавать код с определенным смещением, значит надо будет сбрасывать счетчики после окончания посылки кадра через определенное время, может подскажите алгоритм как лучше это реализовать?