View Categories

Цифровые пины, вход

Для урока понадобится
В наборе GyverKIT Aliexpress
START
Купить
START
IOT
Купить
START
IOT
Купить
START
IOT
Купить

Режим INPUT #

Обязательно изучите вводный цикл уроков про электричество

В данном режиме пин находится в высокоимпедансном состоянии - можно считать, что он подключен к GND последовательно через резистор с сопротивлением в десятки и сотни мегаом - это очень большое сопротивление, практически "обрыв провода", т.е. пин как будто "висит в воздухе". Собственно МК будет измерять напряжение на данном резисторе:

Таким образом, если подключить к нему GND - вольтметр покажет 0, а если подключить VCC - всё это напряжение упадёт на резисторе и МК его измерит. При подключении VCC в цепи пойдёт ничтожно маленький ток (при питании от 5V получится 5 / 100000000 А). Это - измерительная цепь, она практически не потребляет энергию.

Нельзя подавать на пин в режиме входа напряжение выше напряжения питания МК или отрицательное напряжение!

Чтение пина #

Для измерения цифрового сигнала на пине используется функция digitalRead(пин) (цифровое чтение), где пин - номер пина по распиновке. Давайте соберём простую схему и измерим сигнал на пине:

void setup() {
    Serial.begin(115200);
    //pinMode(2, INPUT);    // пин по умолчанию как вход, можно не указывать
}

void loop() {
    bool signal = digitalRead(2);
    Serial.println(signal);
    delay(100);
}

В первом случае в порт будет печататься 1 - высокий сигнал, а во втором - 0 - низкий. Аккуратно подключайте провод поочерёдно к 5V и GND, не отключая плату от компьютера - значение в мониторе порта будет меняться.

Оставьте провод подключенным к D2 и просто держите его в руках или подключите куда-нибудь в свободное место на макетке (справа от платы). С большой вероятностью в порт пойдут случайные значения 001001100111010100101010 - дело в том, что провод как антенна "ловит" различные наводки из воздуха: окружающего оборудования и сетевых проводов.

Какое напряжение на GPIO МК считает за 0, а какое за 1? Это указано в документации на МК, например для Arduino Nano (ATMega328p) за 0 считается напряжение от -0.5 V до 0.3 VCC, а за 1 - от 0.7 VCC до VCC + 0.5, где VCC это напряжение питания. При питании от 5V получится логический ноль при (-0.5.. 1.5)V и единица при (3.5.. 5.5)V

Чтение с OUTPUT #

Чтение сигнала с пина работает в любом режиме, т.е. пин может измерить и напряжение, которое сам на себя подал. Наглядный пример - перепишем мигающий светодиод из прошлого урока, заменив конструкцию включить и выключить на переключить. Для этого нужно просто подать на пин сигнал, противоположный текущему измеренному - !digitalRead(пин), где восклицательный знак - инверсия:

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);       // сделать пин выходом
}

void loop() {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));   // переключить (подать обратное)
    delay(500);                         // ждать 500 мс
}

Push-pull и open-drain #

Есть две большие группы источников (выходов) цифрового сигнала:

  • Push-pull (толкать-тянуть) или активный выход - источник выдаёт активный высокий и низкий сигналы. Это как мы в примере выше переключали провод между VCC и GND
  • Open-drain (открытый коллектор) - источник выдаёт только низкий сигнал, вместо высокого он переходит в высокоимпедансное состояние (отключается от пина). Это как если в примере выше мы будем вставлять и вынимать провод из GND, держа его "в воздухе" вместо подключения к VCC

На практике встречаются оба варианта: GPIO микроконтроллера обычно умеет работать в обоих режимах (есть как активный выход, так и высокоимпедансный вход). У простых микросхем часто встречается open-drain, потому что аппаратно это проще и дешевле (один транзистор). Также open-drain позволяет избегать короткого замыкания при реализации передачи данных по одному проводу в обе стороны, например так работает шина I2C и интерфейс One Wire, по которому общаются например термометры DS18b20.

Для чтения push-pull сигнала достаточно подключить его к пину и всё - на пине всегда будет активный стабильный сигнал для чтения. А вот с open-drain всё немного сложнее.

Чтение open-drain #

Высокоимпедансное состояние удобно тем, что не потребляет энергию. Но у него есть и серьёзный минус - если пин никуда не подключен, то он имеет неопределённое состояние со случайным сигналом. Если в реальном устройстве от такого пина "отвалится" провод - МК начнёт получать с него случайные значения. Страшно представить что случится, если это кнопка - она может "натыкать" в устройстве всё что угодно! Более того, обычно кнопка имеет всего два контакта, то есть может только замыкать и размыкать цепь. Если мы подключим кнопку вот так:

То при нажатии она будет подавать на пин стабильные 5V, их можно будет точно измерить. А вот если отпустить кнопку - пин начнёт получать случайные значения.

У типичной тактовой кнопки контакты соединены следующим образом:

Подключите её и посмотрите что получится. Программа та же, что выше:

При нажатии будет стабильная единица 1, а при отпускании могут пойти случайные значения.

Подтяжка #

Для решения неопределённого поведения используется подтяжка - в схему добавляется резистор с сопротивлением порядка нескольких десятков кОм, который устанавливает на пине стабильное напряжение, пока кнопка не нажата. Подтяжка делается к противоположному от кнопки полюсу - если резистор подтягивает к VCC - подтяжка называется pull-up, если к GND - pull-down:

Кнопка может быть подключена по разному, а вот в случае с open-drain выходом всегда нужна подтяжка к питанию. Например - датчик температуры DS18b20:

Если сопротивление подтяжки слишком маленькое (сотни Ом) - через неё будет идти большой ток (трата энергии, нагрев), а если слишком большое (сотни кОм) - могут "пробиться" помехи. Типичное сопротивление подтяжки - единицы и десятки кОм, на практике чаще всего встречается 10 кОм

Добавьте внешнюю подтяжку в схему двумя способами и понажимайте кнопку, программа та же:

В первом случае нажатая кнопка - это сигнал 1, а во втором - 0.

Режим INPUT_PULLUP #

Для удобства подключения кнопок и прочих open-drain устройств МК часто имеют внутреннюю подтяжку в несколько десятков кОм (см. доку на конкретный МК), она активируется через pinMode(). В этом режиме никуда не подключенный пин будет выдавать стабильный высокий сигнал. Давайте добавим этот режим на тот же пин и подключим кнопку без внешних резисторов:

void setup() {
    Serial.begin(115200);
    pinMode(2, INPUT_PULLUP);
}

void loop() {
    bool signal = digitalRead(2);
    Serial.println(signal);
    delay(100);
}

Теперь кнопка может стабильно опрашиваться без внешних резисторов, выдавая 0 при нажатии и 1 при отпускании. Об алгоритмах опроса кнопки читайте в соответствующем уроке.

Пин, к которому подключен светодиод на плате (13 на Arduino Nano/UNO) некорректно работает в режиме INPUT_PULLUP - имеет сигнал LOW, так как подключенный светодиод тянет его к GND через свой резистор!

Дополнительно #

Дополнительный контент доступен владельцам набора GyverKIT и по подписке, подробнее читай здесь. Блок содержит:

  • Тезисы

Полезные страницы #

(1 голос)
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх