======GPIO - Настройка портов ввода-вывода======
GPIO - General Purpose Input Output это выводы микроконтроллера, которые можно настраивать под свои цели. Они могут использоваться просто как порты на вывод и вход, например логических "0" и "1". Могут иметь дополнительные, например аналоговые функции для работы с АЦП. Могут использоваться аппаратно для реализации различных интерфейсов взаимодействия, например UART, SPI и т.д. Количество портов в каждом процессоре разное, как и распределение по ним дополнительных функций. Информацию по данному вопросу необходимо смотреть в спецификации в разделе "Порты ввода вывода MDP_PORTx"
Работа порта ближе к схемотехнике рассмотрена в [[doc:doclist:gpio_schm|"Схемотехника портов GPIO"]].
=====Управление портами на примере функций SPL.=====
Функции SPL реализуют настройку и управление портами через именованные поля, структуры и значения. Каждый параметр настройки имеет свое отдельное поле в структуре, в большинстве своем имеет перечислимый тип значения этого поля и краткое описание в комментариях. Это очень удобно и позволяет избежать ошибок при работе. Кроме этого, одна и та же функция SPL реализует одинаковое поведение для всех поддерживаемых SPL процессоров. То есть поля в регистрах или сами регистры, их адреса могут отличаться, от процессора к процессору, но функция вызванная с одинаковым аргументом выполнит одинаковое действие. Таким образом реализуется стандартное поведение функций при различии реализации в железе.
Минусом использования SPL является больший размер программы (прошивки) и сниженное быстродействие. Зато сводится к минимуму возможность совершить ошибку. Поэтому для освоения программирования рекомендуется начинать работу с функциями SPL, добиваться работоспособности проекта, а затем модифицировать критические куски кода к регистровому исполнению.
Настройку порта рассмотрим на примере использования порта PORT_C вывод pin_0, сокращенно PC0. Этот вывод используется в программе [[PROG:Start:HelloWord|"Hello World - светодиод"]].
==== Инициализация порта ====
// Включаем тактирование порта C
RST_CLK_PCLKcmd (RST_CLK_PCLK_PORTC, ENABLE);
Первым действием всегда включается тактирование. Подробнее - [[doc:doclist:core_clock|Тактирование процессора]].
// Инициализируем структуру конфигурации вывода(-ов) порта значениями по умолчанию
PORT_StructInit(&GPIOInitStruct);
Функция PORT_StructInit заполняет структуру конфигурации порта значениями по умолчанию.
void PORT_StructInit(PORT_InitTypeDef* PORT_InitStruct)
{
/* Reset PORT initialization structure parameters values */
PORT_InitStruct->PORT_Pin = PORT_Pin_All;
PORT_InitStruct->PORT_OE = PORT_OE_IN;
PORT_InitStruct->PORT_PULL_UP = PORT_PULL_UP_OFF;
PORT_InitStruct->PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;
PORT_InitStruct->PORT_PD_SHM = PORT_PD_SHM_OFF;
PORT_InitStruct->PORT_PD = PORT_PD_DRIVER;
PORT_InitStruct->PORT_GFEN = PORT_GFEN_OFF;
PORT_InitStruct->PORT_FUNC = PORT_FUNC_PORT;
PORT_InitStruct->PORT_SPEED = PORT_OUTPUT_OFF;
PORT_InitStruct->PORT_MODE = PORT_MODE_ANALOG;
}
=== PORT_Pin ===
Это маска выбора выводов для которых будет применена данная конфигурация. Возможны варианты PORT_Pin_0 .. PORT_Pin_15, PORT_Pin_All и всевозможные варианты масок из этих значений. Например, для применения конфигурации к выводам 0 и 1 используется PORT_Pin = PORT_Pin_0 | PORT_Pin_1.
В процессоре 1986ВЕ92У есть 6 портов ввода вывода (A, B, C, D, E, F). Обычно каждый порт имеет по 16 выводов (ножек), которые можно настроить по отдельности. Но количество выводов у микросхемы может быть сокращено в целях экономии, например у данного процессора в корпусе LQFP64 порт А имеет только выводы PA0 - PA7. Название вывода берется из названия порта и номера вывода.
=== PORT_OE ===
Это поле настраивает порт на вывод данных или на вход. Возможные варианты PORT_OE_OUT и PORT_OE_IN, в первом случае мы будем писать в порт, а во втором считывать из порта.
=== PORT_PULL_UP и PORT_PULL_DOWN ===
Эти параметры задают подтяжку вывода к линии питания или земли. Обычно это используется когда вывод используется как вход. Резистор подтяжки составляет порядка ~50КОм, точное значение необходимо уточнять в спецификации на микропроцессор.
Возможные варианты значений для PORT_PULL_UP это PORT_PULL_UP_OFF и PORT_PULL_UP_ON, а для PORT_PULL_DOWN соответственно PORT_PULL_DOWN_OFF и PORT_PULL_DOWN_ON. Важно не путать эти значения, нельзя например сделать так PORT_PULL_DOWN = PORT_PULL_UP_OFF. Очень часто значения являются определенными битовыми масками, которые в итоге должны расположиться в по нужному смещению в регистре. Поэтому PORT_PULL_UP_OFF не равно PORT_PULL_DOWN_OFF, и важно их не путать.
=== PORT_PD_SHM ===
Этот параметр включает - выключает использование триггера Шмитта. Этот триггер известен тем, что имеет гистерезис и при некотором отклонении напряжения dU от заданного логического уровня на входе сохраняет текущее логическое значение на выходе. Например, если если ножка настроена на вход и напряжение на ней равно напряжению питания, то микроконтроллер трактует это, как наличие логической "1" на входе. Если в какой-то момент на линии появится помеха, или наводка такая, что напряжение на входе просядет меньше чем на dU, то микропроцессор будет по прежнему трактовать это как логическая "1". С логическим нулем ситуация аналогичная.
Это поле может принимать следующие значения, при PORT_PD_SHM_OFF dU = 200 мВ, а при PORT_PD_SHM_On = 400 мВ.
=== PORT_PD ===
Параметр определяет подключение вывода как управляемый драйвер PORT_PD_DRIVER, либо как открытый сток - PORT_PD_OPEN.
PORT_PD_DRIVER - обычный режим работы, его еще называют тяни-толкай (push-pull). Это режим с двумя устойчивыми состояниями "0" и "1". Когда мы пишем "1" то вывод через полевые транзисторы подключается к цепи питания и отключается от земли, таким образом на выходе появляется напряжение питания. Когда записывается в порт логический "0", то отключается питание и подключается земля, так формируется 0 на выводе.
В режиме PORT_PD_OPEN вывод отключается от транзистора коммутирующего его с цепью питания, то есть мы может только просаживать внешнюю линию на 0, а при записи 1 это "просаживание" отключается. В таком режиме подразумевается, что используется внешняя подтяжка к питанию, как это происходит например на шине I2C.
=== PORT_GFEN ===
Режим работы входного фильтра PORT_GFEN_OFF - выключен и PORT_GFEN_ON - фильтрация импульсов до 10 нс.
===PORT_MODE===
Параметр определяет в каком режиме будет работать вывод контроллера в аналоговом PORT_MODE_ANALOG или в цифровом PORT_MODE_DIGITAL. Аналоговый режим используется, например, когда через ножку заводится аналоговый сигнал для оцифровки внутренним АЦП. При выводе аналогового сигнала от встроенного ЦАП используется такой же режим.
Назначение ножек при использовании в аналоговом режиме следует смотреть в спецификации раздел "Порты ввода - вывода". Например, в семействе 1986ВЕ9х вывод РЕ9 (Port_E, вывод порта 9) является выводом встроенного DAC1.
===PORT_FUNC===
Данный параметр задает какую функцию будет исполнять порт в цифровом режиме. Есть четыре варианта значений этого параметра. Основная функция это PORT_FUNC_PORT - вывод используется как стандартный порт ввода-вывода. В этом режиме мы сами пишем и читаем состояние вывода микроконтроллера. В остальных режимах PORT_FUNC_MAIN, PORT_FUNC_ALTER, PORT_FUNC_OVERRID вывод используется в аппаратно реализованных алгоритмах, например UART, SPI и прочих.
Как будет использоваться вывод при задании определенной функции необходимо смотреть в спецификации раздел "Порты ввода - вывода". Например, для 1986ВЕ9х вывод РЕ12 в функции MAIN является 28-й линией шины адреса, в функции ALTER - линией RXD в аппаратной реализации SPI, в функции OVERRID - линией RXD в аппаратной реализации UART1.
^ Вывод ^ Analog ^ DIGITAL ^^^^
^ ::: ^ ::: ^ PORT ^ MAIN ^ ALTER ^ OVERRID ^
| РЕ12 | - | РЕ12 | ADDR28 | SSP1_RXD | UART1_RXD |
В аналоговом режиме данный порт не имеет применения.
Если для разных выводов выбрать одну и ту же функцию, например, TMR2_CH2, то реально будет задействован только один вывод, причём выбор активного осуществляется в порядке приоритета по названию порта, т.е. сначала порт А, далее порт B и т.д.
===PORT_SPEED===
Параметр определяет время переключения логических состояний, по существу длительность фронтов. Возможные варианты
* PORT_OUTPUT_OFF - Порт выключен
* PORT_SPEED_SLOW - Медленный фронт, порядка 100нс
* PORT_SPEED_FAST - Быстрый фронт, порядка 20нс
* PORT_SPEED_MAXFAST - Максимально быстрый фронт, порядка 10нс.
При быстрых фронтах возрастает потребление микроконтроллера, но зато можно увеличить скорость работы с подключенной периферией. Для мигания светодиодом скорость не важна и лучше использовать вариант с PORT_SPEED_SLOW.
Работа порта ближе к схемотехнике рассмотрена в [[doc:doclist:gpio_schm|"Схемотехника портов GPIO"]].
=====Управление портами через регистры.=====
SPL делает настройку портов более читаемой, и предохраняет нас от случайных ошибок. В конечном итоге функции SPL задают наши параметры в регистры настроек выводов портов. Эти регистры представлены на следующей картинке, описание же находится в [[doc:doclist:gpio_schm|"Схемотехника портов GPIO"]].
{{doc:doclist:pad_scheme.png}}