Использование нескольких внешних прерываний в PIC

Я использовал PIC16F877( datasheet ) для нескольких проектов. Для одного внешнего прерывания смены контакта вы можете использовать PORTB0прерывание. Но теперь мне нужно поддерживать 8 независимых внешних прерываний смены контактов в одной цепи.

В таблице данных указано, что в 15 прерываний PIC16F877, но я думаю, что они учитываются, включая прерывания переполнения таймера и т. Д., Которые в этом случае бесполезны.

Это то, что даташит говорит о INTCONрегистрации.

введите описание изображения здесь

Могу ли я иметь 4 независимых прерывания, используя бит0, RBIF? Он представляет собой изменение в PB7:PB4. Как я могу определить, какой контакт изменился, прочитав значение порта в процедуре прерывания?

Даже если я получаю положительные ответы на вышеперечисленные вопросы, мне нужно 8 прерываний? конечно, я все еще могу использовать INTEдля PORTB0изменения. Тогда 4 + 1 = 5, а как насчет остальных 3? (Однако, поскольку все 8 событий прерывания имеют один и тот же тип, 4 + 1 + 3 = 8это выглядит некрасиво, не так ли?)

От микроконтроллера не ожидается никаких других тяжелых задач, кроме контроля 8 контактов. (Говоря о других задачах, ему придется поддерживать набор отдельных переменных-счетчиков и часто последовательно передавать на ПК около 4 байтов)

Любые предложения приветствуются. Даже если речь идет о смене микроконтроллера на более подходящий (но эээ.. не говорите мне уйти от PICs).

Не используя прерывания, возможно, вы можете контролировать выводы в основной программе. Но это не идеально. В качестве альтернативы вы можете пойти на Arduino. Хотя это и не ПОС, это довольно просто, вы легко поймете, поскольку уже знакомы с ПОС.
Если вы используете прерывание RBIE, вы можете просто буферизовать предыдущее значение каждый раз и XOR, чтобы найти, что изменилось. Должно быть довольно быстро для выполнения.
@PeterJ, я не совсем это понял. Буфер какое значение?
@PeterJ здорово! ожидающий...
Одним из способов является использование внешнего вентиля с 8 входами (например, 74LS30 в старые времена) для объединения внешних сигналов на один вывод прерывания. Поскольку 74(HC)30 является логическим элементом И-НЕ, вам потребуются все входы высокого уровня в состоянии покоя - они также должны быть подключены к контактам порта, чтобы вы могли определить, какие прерывания были активны, читая порт.
@CodenamedSC, не проще ли переключиться на другой PIC, который поддерживает прерывание при изменении для большего количества контактов? Я думаю, что есть некоторые, которые поддерживают весь порт B.
Как быстро система должна обнаруживать изменения и реагировать на них? Каково минимальное время, в течение которого изменение должно сохраняться, чтобы оно было действительным? Действительно, должно было быть очевидно, что это важные параметры.
@BrianDrummond да, это удобное решение (и, кажется, лучшее). Но единственная проблема в том, что я не люблю возиться с железом сейчас, когда у меня есть законченная схема. Но я обязательно учту это, если мне придется перестраивать его в любом случае. Спасибо!
Я тоже ищу нечто подобное. Мне нужно иметь 8 прерываний. Я делаю систему зуммера обнаружения первого нажатия для QUIZ. Таким образом, голосование несправедливо по отношению к участникам.

Ответы (3)

Это псевдокод C для объяснения одной идеи. Он использует исключающее ИЛИ для определения того, какие выводы были изменены, и будет вызывать ваши разные обработчики в одном прерывании RBIE. В зависимости от того, насколько критично приложение, вы можете проверить, как PIC обрабатывает такие ситуации, как изменение порта во время выполнения прерывания, чтобы убедиться, что вы не пропустите ни одного события.

int old_port_b;

void isr_handler()
{
    int new_port_b, changed_pins;
    new_port_b = read_port_b();
    changed_pins = new_port_b ^ old_port_b;
    if (changed_pins | 1)
        rb0_hander();
    if (changed_pins | 2)
        rb1_hander();
        // ... etc
    old_port_b = new_port_b;
}

int main()
{
    old_port_b = read_port_b();
    enable_interrupt();
}
Я понял, спасибо! но это не точный ответ, который я ищу. Таким образом, вы можете контролировать RB7:RB4только 4 контакта. Но прошу способ мониторить 8 пинов. любое предложение?
Я предполагаю, что есть причина, по которой вы не можете использовать RB0 - RB7, для которой вышеописанное должно работать? В противном случае я не могу придумать способ, если быстрый запуск кода не является жизненно важным, вы можете использовать приведенный выше стиль кода в прерывании по таймеру (или просто в основном цикле).
Для этого PIC, если вам нужно использовать прерывания для этого, трюк XOR для RB4: RB7 и четыре прерывания для RB0: RB3 — это путь. Если вам не нужно прерывание, просто опросите весь порт в своем коде или используйте прерывание по таймеру для обработки опроса, если вам нужна жесткая частота дискретизации.
and four interrupts for the RB0:RB3? PIC16F877 не поддерживает никаких прерываний для RB1:RB3, а?
Я пропустил это в таблице данных, я предполагал, что это покрывает весь порт. Но я видел ваш другой комментарий примерно раз в секунду, поэтому я думаю, что вам лучше просто запустить это в своем основном цикле. С прерываниями вам нужно позаботиться об обновлении переменных в любой момент во время выполнения и о том, как обрабатывать изменения контактов во время работы прерывания. Это действительно звучит так, как будто это просто усложнит его без реальной выгоды. Единственное исключение, о котором я мог подумать, - это если вы хотите использовать выход из спящего режима по прерыванию, и в этом случае вам нужно будет аппаратно MUX.

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

Важными параметрами, которые вы не указали, являются скорость, с которой вам нужно реагировать на смену булавки, и минимальное время, в течение которого смена булавки будет сохраняться, чтобы она была действительной. В зависимости от ответов можно было опросить на основе обычного прерывания в прошивке. 16F877 может работать с частотой команд 5 МГц, и для проверки изменений потребуется всего несколько инструкций. Допустим, вы настроили прерывание каждые 50 инструкций. Это оставило бы значительную часть времени процессора коду переднего плана. Частота прерываний будет 100 кГц, а период 10 мкс. Конечно, код переднего плана все еще должен видеть флаг изменения и что-то с этим делать, поэтому время отклика будет более 10 мкс, но вы ничего не сказали о том, что вам нужно делать при обнаружении изменения. Если это просто нужно ответить в человеческое время,

Извините за недостающие детали. Так как ожидаемой скорости отклика once per secondбудет достаточно. Когда обнаруживается изменение вывода (только один фронт, скажем, рост), счетчик (переменная) должен быть увеличен. В основном цикле он должен отслеживать значения счетчика, и когда одно из них превышает определенное значение, четыре байта должны быть переданы через USARTПК. Затем сбросьте соответствующее значение счетчика на ноль. Просто как тот. Я предполагаю, что вариант опроса пойдет нормально, верно?
Раз в секунду ! Так для чего все эти мучения с прерываниями? Это легко сделать с помощью периодических опросов. В чем тогда проблема?
гм... хотя это будет лучше, так как их 8, а также ответ нельзя предсказать (но это значение можно считать минимальным). Привет! люди могут ошибаться, верно.. :(

Вы можете использовать NAND с 8 входами, как указано @Brian Drummond, чтобы поднять прерывание через вывод INT, а также подключить источники прерывания к 8-битному регистру сдвига Parallel-In / Serial-Out, например «74HC165N», поэтому вам понадобится просто прочитать данные из этого регистра сдвига после возникновения прерывания, и это даст вам информацию о вашем фактическом источнике прерывания ... это может быть не самый быстрый способ, но его легко расширить, и он будет использовать не более 5 контактов, и если вы добавите систему управления адресами (MUX, LATCH,...), то вам понадобится только один контакт для уведомления о прерывании, а другие контакты могут быть повторно использованы в разное время для разных ресурсов;)