-
Notifications
You must be signed in to change notification settings - Fork 62
GPIO revisited
Автор: Эдгар Казиахмедов
В данной статье будут еще раз рассмотрен режим работы цифровой выход системы ввода-вывода, в частности будет сделан акцент на разнице между режимами OpenDrain и PushPull. Данная статья является дополнением к лекции "GPIO".
Как было уже сказано порты ввода-вывода в микроконтроллере STM32 поддерживают 4 основных режима работы: цифровой выход, цифровой вход, аналоговый вход и режим альтернативной функции (Рис. 1). Описание данной периферии находится на стр. 148 справочного описания периферии. Далее все ссылки будет только на этот документ.
Рис. 1. Режимы работы портов ввода-вывода
Одним из наиболее используемых режимов работы портов ввода-вывода является режим цифрового выхода. В данном режиме можно управлять различными устройствами, подключенными к выводам портов. К примерам данных устройств можно отнести светодиоды, семисегментные индикаторы, двигатели и т.д. Для написания кода инициализации и работы к периферией будут использованы функции из главы по GPIO (стр. 829) библиотеки Low Layer.
Если вернуться к блок-схеме, то модуль состоит из двух основных блоков:
- Регистры, отображающие текущее состояние порта:
- ODR - текущее логическое состояние цифр. выхода;
- BSRR - так называемый bit/reset регистр;
- Физический драйвер, работа которого задается следующими конфигурационными регистрами:
- OTYPER - режим работы выходного драйвера (Open-Drain, PushPull);
- OSPEEDR - режим работы выхода по скорости (по сути меняется емкость выхода);
- PUPDR - включение/выключение резистора, подтягивающего к земле, либо к питанию;
Давайте для примера рассмотрим регистр MODER на стр. 157, с помощью которого можно будет сконфигурировать вывод в режим цифрового выхода (Рис. 2)
Рис. 2. Регистр MODER
Регистр состоит из групп по два бита для каждого вывода по отдельности. Стоит заметить, что все выводы по умолчанию находятся в состоянии цифрового входа, а значит по умолчанию активен триггер Шмидта, который будет переключаться из-за любой помехи на входе и, соответственно, потреблять энергию. Для переключения в состояние цифровой выход необходимо записать в соответствующую группу битов значение 01
.
Конечно, писать напрямую в регистр нежелательно, так как это приводит к плохой читабельности кода в будущем. По этой причине в курсе используется библиотека LL, при пролистывании которой можно увидеть функцию LL_GPIO_SetPinMode
, которая как раз и позволяет выставить режим работы вывода путем обычной записи
в тот самый регистр MODER. Для примера можно инициализировать седьмой вывод порта GPIOC
(к которому подключен
один из светодиодов на отладочной плате):
LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);
ACHTUNG: перед работой с любой периферией необходимо подать на нее тактирование, а иначе ничего никогда не заработает, в данном случае:
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOC);
Теперь рассмотрим два режима работы выходного драйвера: PushPull (двухтактный), OpenDrain (с открытым стоком). На схеме устройства оба режима будут выглядеть следующим образом:
Рис. 3. Режим PushPull
Рис. 4. Режим OpenDrain
Как видно, разница лишь заключается в наличии транзистора в верхнем плече. В режиме PushPull при записи единицы выходной драйвер "подключит" выход к питанию, а при записи нуля к земле. То есть на выходе будет либо +3В
, либо 0В
.
В режиме OpenDrain картина будет следующая: при записи единицы выход будет "висеть в воздухе", то есть никуда не подключенный, а при записи нуля будет подключен к земле.
Возникает вопрос, а где вообще может пригодиться режим OpenDrain, когда есть PushPull, который, казалось бы, выполняет все необходимые функции?
Давайте рассмотрим три возможных применения данного режима. Для начала рассмотрим ситуацию, когда необходимо соединить вход и выход у микросхем с разной логикой, для примера 3В
и 5В
:
Рис. 5. Подключение микроконтроллеров с разной логикой
В случае, если используется режим PushPull (представим картину без резистора), входной порт микроконтроллера с трехвольтовой логикой может выйти из строя из-за превышения напряжения на входе. Решением этой проблемы как раз и является использование режима OpenDrain. Проще говоря, теперь логическая единица для МК слева будет означать, что вывод никуда на подключен, поэтому он "подхватывается" подтягивающим резистором на питание +3В
и попадает на вход правого МК, для которого такой входной потенциал уже является нормальным.
Рис. 6. Логическая единица OpenDrain
Рис. 7. Логический ноль OpenDrain
В следующем примере рассмотрим такую задачу: необходимо подключить несколько выходов с N
микроконтроллеров и подать их на один вход N+1
микроконтроллера. Положим N=2
:
Рис. 8. Подключение трех МК
Сначала положим, что резисторов нет и выводы сконфигурированы в режим PushPull. Представим такую ситуацию: два МК слева работают асинхронно и выставили в какой-то момент времени разные выходные состояния, верхний - единицу, нижний - нуль. В таком случае произойдет короткое замыкание, так как максимальный ток потечет от верхнего МК к нижнему (ограничительного резистора нет). В результате чего, выводы могут выйти из строя, так как выгорят внутренние транзисторы (конечно существуют еще и ограничительные диоды, но в целом ситуация крайне опасная). Чтобы избежать такого состояния, переведем все выводы в режим OpenDrain и подключим на каждый вывод подтягивающий резистор. Теперь логическая единица на любом из выводом означает лишь подтягивание к питанию. Получился некий вариант реализации логического элемента "И". На вход третьего МК попадет единица, когда все МК выставят лог. единицу на выходе.
Третий пример касается такого интерфейса как I2C, где используются два вывода SDA (передача данных) и CLK (сигнал синхронизации). К этой шине подключаются участники сети, и для избежания электрических конфликтов, используется режим OpenDrain.
Также в модуле ввода-вывода присутствуют внутренние подтягивающие резисторы, которые можно использовать как и для подтяжки в режиме OpenDrain, но нужно иметь ввиду, что они достаточно маломощные.
Конечно, нет необходимости все время использовать OpenDrain для подключения двух МК с разной логикой, STM32 поддерживает вход 5В
практически для всех входов. Чтобы убедиться, что конкретный вход имеет поддержку входа на 5В
, необходимо открыть описание конкретного подсемейства микроконтроллеров на странице с распиновкой (стр. 31) и посмотреть какой I/O Structure у конкретного входа в таблице. 5V tolerance имеет надпись FT.
Конечно, в статье и в лекции не были рассмотрены абсолютно все возможности данной периферии, но для 99% задач это вполне достаточно. Безусловно, было бы неплохо иметь такую возможность как переотображение любых внутренних выводов на любые физические выводы МК, но данное решение достаточно нетривиально с точки зрения проектирования и внесло бы немало своих ограничений.