Цифровые порты ввода-вывода

Микроконтроллеры / Для начинающих / Архитектура /

Микроконтроллеры для начинающих Что нужно для того, чтобы стать профессиональным разработчиком программ для микроконтроллеров и выйти на такой уровень мастерства, который позволит с лёгкостью найти и устроиться на работу с высокой зарплатой (средняя зарплата программиста микроконтроллеров по России на начало 2017 года составляет 80 000 рублей). Подробнее...

Порты представляют собой двунаправленные порты ввода-вывода с дополнительными внутренними подтягивающими резисторами. На рисунке ниже показано функциональное описание одного порта ввода-вывода (одной ножки микросхемы), который здесь в общем случае называется Pxn.

Общий цифровой порт ввода-вывода AVR

ПРИМЕЧАНИЕ: WRx, WPx, WDx, RRx, RPx и RDx являются общими для всех контактов в пределах одного порта. clkI/O, SLEEP и PUD являются общими для всех портов.

Настройка вывода (ножки микросхемы)

Каждый вывод порта состоит из трех битов регистра: DDxn, PORTxn и PINxn. Доступ к битам DDxn осуществляется по адресу ввода-вывода DDRx, к битам PORTxn - по адресу ввода-вывода PORTx, а к битам PINxn - по адресу ввода-вывода PINx.

Бит DDxn в регистре DDRx выбирает направление этого вывода. Если DDxn записан как логическая единица, то Pxn настраивается как выходной вывод (ножка микросхемы работает как выход). Если в DDxn записан логический ноль, то Pxn настраивается в качестве входного вывода (ножка микросхемы работает как вход).

Если в PORTxn записана логическая единица, когда вывод настроен как входной вывод, активируется (подключается) подтягивающий резистор. Чтобы отключить подтягивающий резистор, в PORTxn должен быть записан логический ноль или вывод должен быть сконфигурирован как выходной вывод. Контакты порта находятся в третьем состоянии, когда выполняется условие сброса, даже если тактовый генератор не запущен.

Если в PORTxn записана логическая единица, когда вывод настроен как выходной вывод, вывод порта устанавливается в высокий уровень (единица). Если в PORTxn записан логический ноль, когда вывод настроен в качестве выходного вывода, вывод порта устанавливается на низкий уровень (ноль).

Переключение вывода (ножки)

Запись логической единицы в PINxn переключает значение PORTxn, независимо от значения DDRxn. Обратите внимание, что команда SBI может использоваться для переключения одного единственного бита в порту.

Переключение между входом и выходом

При переключении между тремя состояниями ({DDxn, PORTxn} = 0b00) и высоким уровнем на выходе ({DDxn, PORTxn} = 0b11) должно возникать промежуточное состояние с включенным подтягиванием {DDxn, PORTxn} = 0b01) или низким уровнем на выходе ({DDxn, PORTxn} = 0b10). Как правило, состояние с включенным подтягиванием полностью приемлемо, поскольку в среде с высоким сопротивлением не заметна разница между сильным высоким выходом (через транзисторы) и подтягиванием (через резисторы). Если это не так, бит PUD в регистре MCUCR может быть установлен так, чтобы отключить все подтягивания во всех портах.

Переключение между входом с подтягиванием и выходом с низким уровнем порождает ту же проблему. Пользователь должен применить либо третье состояние ({DDxn, PORTxn} = 0b00), либо высокое состояние выхода ({DDxn, PORTxn} = 0b10) в качестве промежуточного шага.

В таблице приведены управляющие сигналы для значения на выводе (ножке).

DDxn PORTxn PUD (в MCUCR) I/O Подтяжка Примечание
0 0 X Вход Нет Третье состояние
0 1 0 Вход Да Pxn будет источником тока, если включена внешняя подтяжка.
0 1 1 Вход Нет Третье состояние
1 0 X Выход Нет Низкий уровень на выходе
1 1 X Выход Нет Высокий уровень на выходе

Чтение состояния вывода

Независимо от настройки бита направления данных DDxn, состояние вывода (ножки микросхемы) порта может быть считано через бит регистра PINxn. Как показано на рисунке выше, бит регистра PINxn и предшествующий ему затвор (защёлка) образуют синхронизатор. Это необходимо, чтобы избежать метастабильности, если физический вывод изменяет значение вблизи границы внутренних часов, но это также приводит к задержке. На рисунке ниже показана временная диаграмма синхронизации при считывании значения (состояния вывода), при наличии на нём внешнего сигнала. Максимальная и минимальная задержки распространения сигналов обозначаются tpd,max и tpd,min соответственно.

Синхронизация при чтении вывода

Рассмотрим тактовый период, начинающийся вскоре после первого спадающего фронта системных часов. Защелка закрывается, когда тактовая частота низкая, и становится прозрачной, когда тактовая частота высокая, на что указывает заштрихованная область сигнала SYNC LATCH (ЗАЩЕЛКА СИНХРОНИЗАЦИИ). Значение сигнала фиксируется, когда уровень системных часов (SYSTEM CLK) становится низким. Он синхронизируется в регистре PINxn на последующем положительном фронте синхронизации. Как указано двумя стрелками tpd,max и tpd,min, одиночный переход сигнала на выводе будет задержан между ½ и 1½ системными тактовыми периодами в зависимости от времени подтверждения.

При повторном считывании значения (состояния) вывода, присвоенного программным обеспечением, необходимо ввести команду nop, как показано на следующем рисунке. Команда out устанавливает сигнал ЗАЩЕЛКА СИНХРОНИЗАЦИИ (SYNC LATCH) на положительном фронте тактового сигнала. В этом случае задержка tpd через синхронизатор составляет один системный тактовый период.

Синхронизация при считывании значения вывода, присвоенного программным обеспечением

Следующий пример кода показывает, как установить контакты 0 и 1 порта B в высокий уровень, контакты 2 и 3 в низкий уровень, и определить контакты порта от 4 до 5 в качестве входов с подтяжкой, установленной для контакта 4. Результирующие значения входов считываются снова, но, как обсуждалось ранее, используется инструкция nop, позволяющая считывать значение, недавно присвоенное некоторым выводам.

Пример на ассемблере:

...
; Определяем подтяжку и устанавливаем высокие уровни на выходах
; Определяем направления для выводов порта

ldi r16, (1<<PB4)|(1<<PB1)|(1<<PB0)
ldi r17, (1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0)
out PORTB, r16
out DDRB,  r17
; Вставляем nop для синхронизации
nop
; Читаем порт
in r16, PINB
...

Пример на С:

unsigned char i;
...
/* Определяем подтяжку и устанавливаем высокие уровни на выходах */
/* Определяем направления для выводов порта */
PORTB = (1<<PB4)|(1<<PB1)|(1<<PB0);
DDRB = (1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0);
/* Вставляем nop для синхронизации */
__no_operation();
/* Читаем порт */
i = PINB;
...

ПРИМЕЧАНИЕ: Для сборки программы используются два временных регистра, чтобы минимизировать время с момента установки подтягиваний на выводах 0, 1 и 4 до тех пор, пока биты направления не будут установлены правильно, определяя биты 2 и 3 как низкие и переопределяя биты 0 и 1 как силовые (транзисторные) выходы с высоким уровнем.

Включение цифрового входа и спящего режима

Как показано на первом рисунке, цифровой входной сигнал может быть заземлен на входе триггера Шмитта. Сигнал, обозначенный на рисунке как SLEEP, устанавливается контроллером спящего режима в режиме отключения питания, режиме энергосбережения и режиме ожидания, чтобы избежать высокого энергопотребления, если некоторые входные сигналы остаются плавающими или имеют уровень аналогового сигнала, близкий к VCC/2. Режим ожидания переопределен для выводов порта, включенных в качестве выводов внешнего прерывания. Если запрос внешнего прерывания не включен, режим ожидания активен также для этих выводов. Режим ожидания также переопределяется различными другими альтернативными функциями.

Если логический высокий уровень (единица) присутствует на выводе асинхронного внешнего прерывания, настроенного как “Прерывание по восходящему фронту, нисходящему фронту или любому логическому изменению на выводе”, в то время как внешнее прерывание не включено, соответствующий флаг внешнего прерывания будет установлен при восстановлении из вышеупомянутого спящего режима, поскольку фиксация в этом спящем режиме приводит к логике запрошенного изменения.

Неподключенные выводы

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

Самый простой способ обеспечить определенный уровень неиспользуемого вывода - это включить внутреннее подтягивание. В этом случае подтягивание будет отключено во время сброса. Если важно низкое энергопотребление во время сброса, лучше использовать внешнее подтягивающее устройство. Подключать неиспользуемые контакты непосредственно к VCC или GND нежелательно, так как это может вызвать чрезмерные токи, если вывод случайно сконфигурирован как выход.


Вступить в группу "Основы программирования"

Подписаться на RUTUBE-канал

Подписаться на Дзен-канал

Подписаться на рассылки по программированию

Микроконтроллеры для ЧАЙНИКОВ Микроконтроллеры для ЧАЙНИКОВ

Бесплатная рассылка о микроконтроллерах. Рассылка содержит как бесплатную информацию для начинающих, так и ссылки на платные продукты (книги, видеокурсы и др.) для тех, кто захочет вникнуть в тему более глубоко. Подробнее...

Инфо-МАСТЕР ®
Все права защищены ©
e-mail: mail@info-master.su