Три состояния одного джампера. Еще один способ экономии выводов

   В некоторых устройствах на микроконтроллерах для задания настроек  используются джамперы/переключатели. Обычно они подключены аналогично кнопке и имеют два возможных состояния – HIGH и LOW. Если джампера нет, вывод микроконтроллера с помощью встроенного  резистора  “подтянут к плюсу питания”. Когда джампер подключен, вывод микроконтроллера замкнут на землю.
подключение джампера к микроконтроллеру
   Максимальное число различных установок, которые мы можем получить в этом случае = 2 в степени N, где N – число задействованных выводов. Существует ли простой способ увеличить число возможных комбинаций, не используя для этого дополнительные выводы микроконтроллера? Оказывается да!
   Давайте подключим вывод по приведенной ниже схеме.
подключение джампера к микроконтроллеру
Теперь у джампера будет 3 возможных состояния:
HIGH – джампер соединяет вывод мк с плюсом питания
LOW – джампер замыкает вывод мк на землю
OPEN – джампер не подключен
А число комбинаций возрастет до 3 в степени N, где N – число задействованных выводов.

   Вывод микроконтроллера AVR работающий в режиме входа может быть “подтянут к плюсу питания” с помощью встроенного резистора или (если резистор отключен) находиться в состоянии Hi-Z (высокоимпедансное состояние). Посмотрим, какие логические уровни будут на выводе мк в обоих случаях в зависимости от состояния джампера.
  В состояниях HIGH и LOW мы получаем однозначные результаты. А вот в состоянии OPEN при отключенном подтягивающем резисторе на входе мк может быть любой логический (да и не только) уровень напряжения.

Как выйти из этой ситуации? “Посадить” вывод микроконтроллера через резистор на землю!
подключение джампера к микроконтроллеру
   Pull-up и pull-down резисторы в этом случае образуют делитель напряжения. Номинал pull-down резистора нужно выбрать таким образом, чтобы при включенном подтягивающем резистора на входе мк было напряжение логической единицы.  Согласно описанию на ATmega8A (для других микроконтроллеров данные могут отличаться) сопротивление встроенного подтягивающего резистора ~ 20 – 50 КОм, а уровень логической единицы ?2,7 В. По формуле для делителя напряжения вычисляем:

(R * 5 В)/(50 КОм + R) = 2,7 В
R = (50 КОм * 2,7 В)/(5 В – 2,7 В) = 59 КОм.

   Номинал pull-down резистора должен быть больше 59 КОм. Допустим, мы поставили 100 КОм. Какие логические уровни будут на входе мк в этом случае?
Теперь для всех состояний джампера мы получаем однозначный результат, а значит можем их распознавать.

Вот как будет выглядеть код на Си

//задействован 1-ый вывод порта А
#define PIN 1
#define IO_PIN (PINA & (1<<PIN))
#define PullUpOn() PORTA |= (1<<PIN)
#define PullUpOff() PORTA &= ~(1<<PIN)
enum IO_STATES {HIGH, LOW, OPEN};


unsigned char ioState = 0;
 
DDRA = 0x00;
PullUpOff();
    

if (IO_PIN)
   ioState = HIGH;
else {
   PullUpOn();
   __delay_cycles(10);
   if (IO_PIN)
        ioState = OPEN;
   else
         ioState = LOW;
}
PullUpOff();

   Если при отключенном подтягивающем резисторе на выводе мк 1 – состояние джампера HIGH. Если с включенным подтягивающим резистором на выводе 1 – состояние джампера OPEN, в противном случае состояние LOW.

   Входы микроконтроллера AVR имеют паразитную емкость ~10 пФ. Поэтому при подключении/отключении подтягивающего резистора напряжение на выводе изменяется не мгновенно, а нарастает/спадает. Например, при отключении pullup резистора паразитная емкость будет разряжаться на pulldown резисторе до уровня логического нуля в течении 100 Ком * 10 пФ = 1 мкс (примерно) За это время микроконтроллер вполне успеет выполнить несколько инструкций. Для правильного распознавания состояний джампера необходимо после манипуляций с подтягивающим резистором добавлять небольшую программную задержку, что собственно и сделано в приведенном выше коде.

Ну и напоследок.
Вместо джамперов вполне можно использовать обычные тактовые кнопки.
подключение двух кнопк к одному выводу микроконтроллера
(R1 – опционально, для защиты от дурака)

У вас недостаточно прав для комментирования.