Лучшая практика для обнаружения двух одновременных сигналов на двух входных контактах - PullRequest
3 голосов
/ 26 августа 2011

Мне нужно сделать следующее: у меня есть 2 входных контакта на микроконтроллере, и возможно, что сигнал получен на одном или другом, но также возможно, что оба будут физически связаны снаружи, и сигнал поступает на обоих одновременно.

Проблема: если я использую что-то вроде

if (PINB.1 && PINB.2)
{
  // ...
}

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

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

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

Редактировать : Я знаю по аппаратному обеспечению, что после ребра булавкаудерживайте его значение в течение по крайней мере нескольких десятков миллисекунд.Шум уже позаботился.

PINB.1 и PINB.2 были только примерами.Возможно, они находятся на разных портах, поэтому битовая маскировка всего порта может быть недостаточно гибкой.

Ответы [ 5 ]

5 голосов
/ 26 августа 2011

Вы ответили на свой вопрос: просто используйте таймер и снова проверьте контакты, это самая простая форма цифрового фильтра, которую вы можете использовать. Но вы должны запустить таймер, когда обнаружите изменение уровня булавки. Если у вас очень крутой передний фронт, т. Е. Вывод подключен к некоторой цифровой ИС, то может быть даже достаточно просто прочитать выводы дважды, в зависимости от того, насколько быстродействительны тактовые частоты вашего процессора по сравнению с передним фронтом.

Другим решением является использование чувствительного к фронту прерывания, если MCU имеет эту функцию. Тогда вы гарантированно прочитаете пин-код сразу после изменения. С одним прерыванием для каждого вывода ваша программа может хранить самые последние значения выводов для сравнения ==. Вам нужно будет убедиться, что значения защищены семафорами между прерываниями и «main», иначе вы вернетесь к тому, с чего начали.

4 голосов
/ 27 августа 2011

Вы хотите посмотреть на условие, когда они оба утверждены?Если это так, просто попробуйте их, если не оба утверждены, не беспокойтесь.если это прерывание и вы, вероятно, используете код на C?Даже если ассемблер просто пробует два или три раза, если после прерывания оба не подтверждены, тогда это была ложная сделка и игнорировать ее.

Если вы смотрите на них как на два отдельных события и беспокоитесь о том, сколько раз вы читалипорт, и они оба утверждены.Вы, вероятно, уже должны разделить чтение порта и обработку того, что вы нашли.Считайте порт, если бит 0, затем выполните вещи, если бит 1 (из сохраненного значения, а не повторного чтения порта), затем выполните вещи с битом 1.

Не существует такой вещи, как передовой опыт, кроме "doВаша системная инженерия "(потому что цели проектирования различны в разных отраслях, где используется похожее оборудование).Все эти проблемы и решения покрываются системной инженерией.Ваша системная инженерия скажет вам точно, каково поле для события, о котором вы беспокоитесь, и, зная свойства контроллера / процессора, вы знаете, как система прерываний реагирует, если используется, или какова ваша частота выполнения и выборки, чтобы знать, как свойства микроконтроллеровотносятся к рассматриваемому событию.Я готов поспорить, что выполняя и сохраняя два чтения быстро, затем говорю, что если в одном из этих чтений оба бита подтверждены, объявите, что событие произошло.У вас уже должна быть передискретизация входного сигнала на основе ожидаемого / разработанного сигнала, и в результате вы, вероятно, можете отбросить сэмплы, которые находятся на грани изменения состояния входов.

2 голосов
/ 26 августа 2011

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

Например, допустим, вы установили таймер на 1 мс между битовыми тестами - все, что вы сделали, это «переместите планку» для гонки. Можно ли заставить код действовать так, как будто установлен только один бит, если второй бит становится высоким в 1 пикосекунду после истечения таймера 1 мс? Если да, то почему вы хотите, чтобы это поведение отличалось от того, что происходит с вашим текущим кодом.

Это не значит, что это не будет правильно, просто вы должны понимать, почему это так, если это ваше утверждение. И это зависит именно от того, в чем проблема.

1 голос
/ 26 августа 2011

В реальном мире редко бывает два входа, которые изменяются «одновременно». Если вы знаете, что два входа либо станут активными в течение нескольких интервалов команд друг от друга, либо не станут активными где-либо рядом, вы можете сделать что-то вроде:

  if (INPUT1)
  {
    if (INPUT2 || INPUT2 || INPUT2 || INPUT2)
      handle_double_input();
    else
      handle_input_1_only();
  }
  else if (INPUT2)
  {
    if (INPUT1 || INPUT1 || INPUT1 || INPUT1)
      handle_double_input();
    else
      handle_input_2_only();
  }

INPUT1 и INPUT2 должны быть определены как макросы, которые используют изменяемые квалификаторы, чтобы гарантировать, что входные данные на самом деле опрашиваются, а не кэшируются. Повторяющиеся слагаемые в тесте «если» при обнаружении одного входа должны давать время для переключения другого входа. Количество требуемых повторений может варьироваться в зависимости от максимального перекоса ввода и скорости выполнения контроллера.

1 голос
/ 26 августа 2011

Во избежание трудно повторяющихся ошибок встроенная прошивка должна соответствовать следующей схеме:

  1. чтение и буферизация ввода
  2. вычисление буферизованных выходов из буферизованных входов
  3. буферизованная запись вывода

Другими словами, вы переходите от непрерывной временной области к дискретной. Это как создание снимков реального непрерывного мира. Если этого не сделать, вы получите входные сигналы, которые изменяются в середине вычислений с непредсказуемыми и неповторимыми результатами.

Как говорится, если вы прочитаете [0 1] или [1 0], это будет вход для последующих вычислений. Вы прочитаете [1 1] при следующем запуске.

Вы не можете быть уверены, что можете сэмплировать [1 1], даже если вы подключите один и тот же сигнал к двум контактам одного и того же порта: существуют аппаратные допуски, которые делают это невозможным.

...