Перейти к содержанию

GPIO STM32: порты ввода-вывода STM32F1 и STM32F4

Как устроен вывод STM32 и как им управлять: восемь режимов и их коды в регистрах STM32F1 и STM32F4, атомарная запись через BSRR, альтернативные функции и ремап, скорость выходного каскада, допустимые токи и уровни по даташитам, выводы, выдерживающие 5 В, и примеры на CMSIS.

Обновлено Редакция GAW

GPIO (General-Purpose Input/Output) — порты ввода-вывода общего назначения. У STM32 выводы объединены в порты по 16: GPIOA, GPIOB и дальше по алфавиту, до GPIOG у старших STM32F103 и до GPIOK у STM32F42x/43x. Каждый вывод настраивается отдельно: цифровой вход с подтяжкой или без, двухтактный выход или открытый сток, выход периферии — альтернативная функция — или аналоговый вход для АЦП.

Ниже — два поколения портов, на которых держится большинство проектов: STM32F1 с регистрами CRL и CRH, где режим вывода задаётся четырьмя битами, и STM32F4 с отдельными регистрами MODER, OTYPER, OSPEEDR и PUPDR. Порты новых семейств — F0, F3, G0, G4, L4 и H7 — устроены как у F4, поэтому почти всё, что сказано о нём, к ним тоже относится. Электрические параметры приведены для STM32F103x8/B и STM32F405/407 по их даташитам; у других микроконтроллеров числа свои, но смысл тот же.

Коротко

  • Восемь режимов: вход без подтяжки, с подтяжкой вверх или вниз, аналоговый вход, двухтактный выход, открытый сток и те же два варианта для альтернативной функции.
  • Регистры: у STM32F1 — CRL и CRH (по 4 бита на вывод), у STM32F4 — MODER, OTYPER, OSPEEDR, PUPDR и AFRL/AFRH. Данные — в IDR и ODR, атомарная запись — через BSRR.
  • Ток: до 25 мА на вывод (абсолютный максимум), нормированные уровни при ±8 мА; сумма всех выводов — 150 мА у STM32F103 и 240 мА у STM32F407.
  • 5 В: только на выводы FT, без внутренних подтяжек и при включённом питании.
  • Скорость — это крутизна фронтов, а не частота порта: от 2 до 50 МГц у F1, от Low до Very high у F4.
  • После сброса все выводы — входы без подтяжки, кроме выводов отладчика JTAG и SWD.

Как устроен вывод

У каждого вывода есть выходной каскад, входной триггер Шмитта, две отключаемые подтяжки и защитные диоды. Схема одинакова у STM32F1 и STM32F4 (RM0008, рисунки 13–14; RM0090, рисунок 25), различаются только регистры, которые ей управляют.

Устройство вывода GPIO STM32Слева — регистры и периферия: ODR с регистрами BSRR и BRR и выход альтернативной функции управляют выходным каскадом из транзисторов P-MOS и N-MOS; вход через триггер Шмитта попадает в регистр IDR и во входы периферии; аналоговый путь к АЦП и ЦАП идёт мимо триггера. Справа на линии вывода — отключаемые подтягивающие резисторы к VDD и к земле сопротивлением 30–50 кОм и защитные диоды.АЦП, ЦАПаналоговый входIDRчтение выводаПерифериявход AFBSRR, BRRустановка и сбросODRвыходные данныеПерифериявыход AFтриггер Шмиттавыключаетсяв аналоговом режимеУправление выходомPP или открытый стокVDDP-MOSN-MOSвыходной каскадвыводVDDподтяжка30–50 кОмподтяжка30–50 кОмVDDзащитныедиоды
Упрощённая схема вывода GPIO STM32. У выводов FT, выдерживающих 5 В, верхний защитный диод подключён не к VDD, а к отдельному узлу VDD_FT (RM0008, рисунок 14).
  • Выходной каскад — пара транзисторов P-MOS и N-MOS. В двухтактном режиме (push-pull) единица в регистре ODR открывает P-MOS и подтягивает вывод к VDD, ноль открывает N-MOS и прижимает его к земле. В режиме открытого стока P-MOS не включается никогда: ноль по-прежнему тянет линию вниз, а единица оставляет вывод в высокоимпедансном состоянии.
  • Источник сигнала для каскада — либо регистр ODR, либо выход периферии (альтернативная функция): в режиме AF выходной регистр от вывода отключается.
  • Входной триггер Шмитта работает во всех цифровых режимах, в том числе на выходе: состояние вывода попадает в регистр IDR на каждом такте шины — APB2 у STM32F1 и AHB1 у STM32F4. Поэтому по IDR можно проверить, что на самом деле происходит на линии с открытым стоком.
  • Подтяжки вверх и вниз — резисторы 30–50 кОм, типовое значение 40 кОм (DS5319, таблица 36; DS8626, таблица 48). У STM32F407 исключение — PA10 и PB12, выводы ID интерфейсов USB OTG: 7–14 кОм.
  • Аналоговый режим отключает и выходной каскад, и подтяжки, и триггер Шмитта. Вход триггера больше не болтается между порогами и не потребляет ток, а IDR в этом режиме читается как 0 (RM0008, 9.1.10; RM0090, 8.3.12).

Режимы и их коды

РежимSTM32F1: CNF, MODESTM32F4: MODER, OTYPER, PUPDR
Вход без подтяжкиCNF = 01, MODE = 00MODER = 00, PUPDR = 00
Вход с подтяжкой вверхCNF = 10, MODE = 00, бит ODR = 1MODER = 00, PUPDR = 01
Вход с подтяжкой внизCNF = 10, MODE = 00, бит ODR = 0MODER = 00, PUPDR = 10
АналоговыйCNF = 00, MODE = 00MODER = 11
Выход, двухтактныйCNF = 00, MODE = 01, 10 или 11MODER = 01, OTYPER = 0
Выход, открытый стокCNF = 01, MODE = 01, 10 или 11MODER = 01, OTYPER = 1
Альтернативная функция, двухтактныйCNF = 10, MODE = 01, 10 или 11MODER = 10, OTYPER = 0, номер AF в AFRL или AFRH
Альтернативная функция, открытый стокCNF = 11, MODE = 01, 10 или 11MODER = 10, OTYPER = 1

Таблица составлена по RM0008 (таблицы 20 и 21) и RM0090 (таблица 36). У STM32F1 поле MODE одновременно выбирает направление и скорость: 00 — вход, 01 — выход до 10 МГц, 10 — до 2 МГц, 11 — до 50 МГц. Подтяжка входа у F1 выбирается не отдельным битом, а битом ODR того же вывода: единица — вверх, ноль — вниз. В выходных режимах STM32F1 подтяжки выключены, а у STM32F4 их можно включить и для выхода — например, открытый сток с внутренней подтяжкой вверх.

У STM32F1 четыре бита на вывод — 32 бита на восемь выводов, поэтому регистров два: CRL для выводов 0–7 и CRH для 8–15. После сброса в обоих 0x4444 4444: CNF = 01 и MODE = 00, то есть все выводы — входы без подтяжки. У STM32F4 на вывод приходится по два бита в MODER, OSPEEDR и PUPDR и один бит в OTYPER. Поля всех регистров с кодами и значениями после сброса разобраны на страницах GPIO STM32F1 и GPIO STM32F4, там же — конструктор значения регистра.

Какой режим выбрать для периферии

У STM32F4 всё просто: вывод периферии переводится в режим альтернативной функции (MODER = 10), а номер функции записывается в AFRL или AFRH; вход АЦП и выход ЦАП — в аналоговый режим. У STM32F1 номера функции нет, и для входов периферии используется обычный режим входа. RM0008 (раздел 9.1.11) даёт настройки для каждого блока, основные из них:

СигналРежим у STM32F1
USART TX, SPI SCK и MOSI ведущего, выходы таймеров, CAN TX, MCOальтернативная функция, двухтактный
USART RX, CAN RX, SPI MISO ведущеговход без подтяжки или с подтяжкой вверх
входы захвата таймеров, ETR, BKIN, SPI SCK ведомоговход без подтяжки
I²C SCL и SDAальтернативная функция, открытый сток
входы АЦП, выходы ЦАПаналоговый
линии внешних прерываний EXTIвход без подтяжки, с подтяжкой вверх или вниз

Двунаправленные сигналы периферии — например, SDA шины I²C — настраиваются как выход альтернативной функции: входной триггер при этом продолжает работать и передаёт уровень линии в периферию (RM0008, 9.1.4).

Состояние после сброса и выводы отладчика

Во время сброса и сразу после него альтернативные функции выключены, а все выводы — входы без подтяжки. Исключение — выводы отладочного порта, которые сразу после сброса принадлежат отладчику и имеют подтяжки (RM0008, 9.1.1; RM0090, 8.3.1):

ВыводСигналПодтяжка после сброса
PA13JTMS / SWDIOвверх
PA14JTCK / SWCLKвниз
PA15JTDIвверх
PB3JTDO / TRACESWOнет
PB4NJTRSTвверх

У STM32F4 это видно прямо в значениях регистров после сброса (RM0090, 8.4): GPIOA_MODER = 0xA800 0000 — PA13, PA14 и PA15 в режиме альтернативной функции, GPIOB_MODER = 0x0000 0280 — PB3 и PB4 тоже; GPIOA_PUPDR = 0x6400 0000 и GPIOB_PUPDR = 0x0000 0100 — подтяжки из таблицы выше; GPIOA_OSPEEDR = 0x0C00 0000 и GPIOB_OSPEEDR = 0x0000 00C0 — у PA13 и PB3 самая высокая скорость. Отсюда частая ошибка: запись GPIOA->MODER = значение целиком переводит PA13 и PA14 в другой режим, и отладчик теряет связь с микроконтроллером. Меняйте только поля нужных выводов.

У STM32F1 выводы JTAG освобождаются полем SWJ_CFG регистра AFIO_MAPR: 001 — без NJTRST, 010 — JTAG выключен, SWD работает (освобождаются PA15, PB3 и PB4), 100 — выключен и SWD (RM0008, 9.4.2 и 31.4.4). Перед записью в регистры AFIO нужно включить тактирование AFIO битом AFIOEN в RCC_APB2ENR, а биты SWJ_CFG только записываются — при чтении их значение не определено. AN4899 (раздел 6.6) добавляет: если вывод отладчика используется для другой цели, не прижимайте к нулю вывод с подтяжкой вверх и наоборот, пока подтяжка включена, — через неё потечёт лишний ток.

Ещё несколько выводов зависят от других блоков. PC14 и PC15 — это и выводы кварца 32,768 кГц OSC32_IN и OSC32_OUT: портами они работают, пока генератор LSE выключен (RM0008, 9.3.1; RM0090, 8.3.13). Выводы основного кварца у STM32F103 в корпусах на 36, 48 и 64 вывода можно превратить в PD0 и PD1 битом PD01_REMAP регистра AFIO_MAPR, но внешних прерываний на них не будет (RM0008, 9.3.2).

Чтение и запись: IDR, ODR, BSRR

  • IDR — только чтение: младшие 16 бит показывают уровни выводов.
  • ODR — выходные данные. Писать в него можно, но изменение одного бита — это чтение, изменение и запись. Если между чтением и записью произойдёт прерывание, которое меняет другой вывод того же порта, его изменение пропадёт.
  • BSRR — атомарная установка и сброс. Единица в бите n (0–15) устанавливает бит n регистра ODR, единица в бите n + 16 сбрасывает его, нули ничего не делают. Это одна запись по шине: прерывание её не разорвёт, а остальные выводы порта не затрагиваются. Если в одной записи задать и установку, и сброс одного вывода, победит установка (RM0008, 9.2.5; RM0090, 8.3.5).
  • BRR — только у STM32F1: 16-битный регистр сброса, единица в бите n сбрасывает вывод n. У STM32F4 для сброса пишут в старшую половину BSRR.

Есть и различие в доступе: регистры GPIO STM32F1 читаются и пишутся только 32-битными словами (RM0008, 9.1 и 9.2), а у STM32F4 допустимы слова, полуслова и байты (RM0090, 8.3).

Драйверы ST пишут в порты так же. HAL_GPIO_WritePin записывает в BSRR маску вывода или маску, сдвинутую на 16 бит. LL_GPIO_SetOutputPin пишет в BSRR, LL_GPIO_ResetOutputPin — в BRR у STM32F1 и в старшую половину BSRR у STM32F4. HAL_GPIO_TogglePin и LL_GPIO_TogglePin сначала читают ODR, а потом одной записью в BSRR сбрасывают выводы, которые были в единице, и устанавливают остальные: соседние выводы порта при этом не страдают, но если тот же вывод переключить из прерывания между чтением и записью, одно переключение потеряется.

Альтернативные функции и ремап

У STM32F4 перед каждым выводом стоит мультиплексор на 16 входов AF0–AF15, номер выбирается четырьмя битами в AFRL (выводы 0–7) или AFRH (8–15); в CMSIS это массив AFR[0] и AFR[1]. Одновременно к выводу подключена только одна функция, а одна и та же функция периферии обычно доступна на нескольких выводах. У STM32F405/407 номера распределены по блокам (RM0090, рисунок 26):

AFПериферияAFПериферия
AF0системные: JTAG и SWD, MCO, RTC_REFINAF8USART4–6
AF1TIM1, TIM2AF9CAN1, CAN2, TIM12–14
AF2TIM3–5AF10USB OTG FS и HS
AF3TIM8–11AF11Ethernet
AF4I2C1–3AF12FSMC, SDIO, OTG HS
AF5SPI1, SPI2AF13DCMI
AF6SPI3AF14—
AF7USART1–3AF15EVENTOUT

После сброса все выводы подключены к AF0. Какие именно сигналы стоят на конкретном выводе, указано в таблице альтернативных функций даташита и в атласе: например, у STM32F407VE вывод PA2 — это USART2_TX на AF7, TIM2_CH3 на AF1 и ETH_MDIO на AF11. У STM32F42x/43x распределение шире: на AF5 добавлены SPI4–SPI6, на AF6 — SAI1, на AF8 — UART7 и UART8, на AF9 и AF14 — контроллер дисплея LTDC (RM0090, рисунок 27).

У STM32F1 мультиплексора нет: периферия подключается к своим выводам, как только её включили, а вывод нужно перевести в нужный режим из таблицы выше. Если выводы по умолчанию заняты или неудобны, часть функций можно перенести на другие выводы — это называется ремап и задаётся битами регистров AFIO_MAPR и AFIO_MAPR2. Например, бит USART1_REMAP переносит USART1 с PA9 и PA10 на PB6 и PB7, а поле CAN_REMAP переносит CAN с PA11 и PA12 на PB8 и PB9 (RM0008, раздел 9.3). Варианты ремапа каждого вывода показаны на страницах атласа, например у STM32F103C8, а все биты — на странице регистров AFIO.

Скорость выходов

Скорость вывода — это крутизна фронтов выходного каскада, от которой зависит, при какой частоте и ёмкости нагрузки сигнал ещё успевает доходить до уровней. Частота, с которой программа может переключать порт, от неё не зависит. У STM32F1 скорость задаётся полем MODE (DS5319, таблица 38):

MODEНазваниеНаибольшая частотаФронт и спад, не больше
102 МГц2 МГц при 50 пФ125 нс
0110 МГц10 МГц при 50 пФ25 нс
1150 МГц50 МГц при 30 пФ и VDD 2,7–3,6 В; 30 МГц при 50 пФ; 20 МГц при 50 пФ и VDD 2–2,7 В5 нс при 30 пФ, 8 нс при 50 пФ

У STM32F4 — полем OSPEEDR, четыре ступени (DS8626, таблица 50; названия по RM0090, 8.4.3):

OSPEEDRНазваниеЧастота при VDD > 2,7 ВЧастота при VDD > 1,8 ВЧастота при 10 пФ и VDD > 2,7 ВФронт и спад при VDD > 2,7 В
00Low4 МГц при 50 пФ2 МГц8 МГц100 нс при 50 пФ
01Medium25 МГц при 50 пФ12,5 МГц50 МГц10 нс при 50 пФ
10High50 МГц при 40 пФ25 МГц100 МГц6 нс при 40 пФ
11Very high100 МГц при 30 пФ50 МГц180 МГц4 нс при 30 пФ

Частоты в обеих таблицах даны для скважности 45–55 % на указанной ёмкости. На скоростях High и Very high RM0090 (раздел 9.1) рекомендует включить ячейку компенсации выводов — бит CMP_PD регистра SYSCFG_CMPCR, готовность показывает флаг READY. Она подстраивает крутизну фронтов и снижает помехи по питанию, но работает только при питании 2,4–3,6 В.

Быстрые фронты дают большие импульсы тока, электромагнитные помехи и помехи по питанию при одновременном переключении многих выходов, поэтому ST советует выбирать самую медленную скорость, при которой сигнал успевает (AN4899, раздел 7.2). Ориентир даёт определение наибольшей частоты в DS5319 (рисунок 30): сумма фронта и спада должна быть не больше двух третей периода. Светодиоду, реле или сигналу разрешения хватит самой медленной ступени, а частота выше 1 МГц требует проверки по таблицам выше с учётом ёмкости линии. На потребление скорость не влияет: динамический ток вывода равен I = CL · VDD · f и зависит только от ёмкости нагрузки, напряжения и частоты переключения (AN4899, раздел 5.1.3). Например, выход тактовой частоты 8 МГц на нагрузку 20 пФ при 3,3 В потребляет 20 пФ · 3,3 В · 8 МГц ≈ 0,53 мА.

Токи и уровни

ПараметрSTM32F103 (DS5319)STM32F407 (DS8626)
Ток одного вывода, абсолютный максимум25 мА25 мА
Сумма токов по VDD и по VSS, абсолютный максимум150 мА240 мА
Уровни при токе ±8 мА (8 выводов сразу)низкий ≤ 0,4 В, высокий ≥ VDD − 0,4 Втак же
Уровни при токе ±20 мА, VDD 2,7–3,6 Внизкий ≤ 1,3 В, высокий ≥ VDD − 1,3 Втак же
PC13, PC14, PC15не больше ±3 мА, до 2 МГц и 30 пФтак же, и PI8
Порог низкого уровня на входене выше 0,35 VDDне выше 0,3 VDD
Порог высокого уровня на входене ниже 0,65 VDDне ниже 0,7 VDD
Гистерезис триггера Шмитта200 мВ, у FT — 5 % VDD, не меньше 100 мВ10 % VDD, не меньше 200 мВ
Подтяжки30–50 кОм30–50 кОм, у PA10 и PB12 — 7–14 кОм
Ток утечки входа±1 мкА, у FT при 5 В — 3 мкАтак же
Ёмкость вывода5 пФ5 пФ
Наведённый ток через защитные диодыFT: −5/+0 мА, остальные ±5 мА, сумма ±25 мАтак же

Значения — из таблиц 7, 36 и 37 DS5319 и таблиц 12, 48 и 49 DS8626. Ток 25 мА — предел, за которым микросхему можно повредить, а не рабочий режим: уровни на выходе даташит гарантирует только при 8 и 20 мА. При этом сумма токов всех выводов вместе с потреблением самого микроконтроллера не должна выйти за 150 или 240 мА, так что десяток выводов по 20 мА одновременно — уже перебор.

PC13, PC14 и PC15 (у STM32F407 ещё PI8) питаются через ключ домена резервного питания, который пропускает не больше 3 мА. Поэтому на них нельзя вешать нагрузку, питающуюся от вывода, — например, светодиод, включённый между выводом и землёй (примечание к таблице выводов DS5319 и к таблице 49 DS8626). На плате Blue Pill светодиод стоит на PC13 и включён на втекающий ток: он подключён к питанию и зажигается, когда вывод прижимает его к земле (STM32-base) — но и втекающий ток PC13 ограничен теми же 3 мА.

Для светодиода на обычном выводе ток удобно ограничить 8 мА: тогда даташит гарантирует уровни. Если прямое напряжение светодиода около 2 В, при питании 3,3 В резистор должен быть не меньше (3,3 − 2,0) В/8 мА ≈ 160 Ом — из ряда E24 подойдёт 180 Ом. Подробнее — в калькуляторе резистора для светодиода. Белому светодиоду с прямым напряжением около 3,5 В питания 3,3 В не хватит вовсе: для него AN4899 (раздел 5.3.1) предлагает открытый сток с питанием светодиода от 5 В или внешний транзистор.

Внутренние подтяжки и I²C

Внутренние подтяжки 30–50 кОм годятся для кнопок и чтобы задать уровень неиспользуемого входа, но для шины I²C они слишком слабы. Время нарастания фронта от 0,3 до 0,7 VDD равно 0,8473 · R · C (AN4899, раздел 5.1.5): при типовых 40 кОм и ёмкости линии 100 пФ это 3,4 мкс, а спецификация I²C UM10204 допускает 1000 нс в стандартном режиме 100 кГц и 300 нс на 400 кГц. Нужны внешние резисторы — расчёт в статье об интерфейсе I²C и в калькуляторе подтягивающих резисторов. DS5319 (раздел 5.3.16) отмечает ещё одну особенность: выводы I²C STM32F103 — не «настоящий» открытый сток. Транзистор P-MOS в этом режиме выключен, но физически присутствует.

Выводы, выдерживающие 5 В

В таблице выводов даташита у каждого вывода указан тип. FT (five-volt tolerant) — вывод, к которому можно подключить сигнал 5 В; у остальных выводов вход ограничен VDD + 0,3 В. У STM32F103 и STM32F407 рабочий диапазон входа FT — от −0,3 до 5,5 В при питании 2–3,6 В и до 5,2 В при питании 2 В и ниже (DS5319, таблица 9; DS8626, таблица 14). Абсолютный максимум — VDD + 4 В. Условий несколько:

  • Подтяжки выключены. Чтобы держать на выводе больше VDD + 0,3 В, внутренние подтяжки вверх и вниз должны быть отключены (примечания к таблицам 9 и 36 DS5319, 14 и 48 DS8626): иначе ток пойдёт через резистор в шину питания.
  • Нет аналоговой функции. В аналоговом режиме вывод не выдерживает 5 В (RM0090, 8.3.12), а пока к нему подключён вход АЦП, напряжение не должно превышать VDDA или VREF+ больше чем на 0,3 В (AN4899, раздел 5.2.2).
  • Микроконтроллер запитан. Без питания, когда VDD = 0, на вывод FT нельзя подавать больше 3,6 В (AN4899, разделы 5.2.2 и 6.3). Если внешняя схема с питанием 5 В может включиться раньше STM32, ограничьте ток в вывод резистором или стабилитроном.
  • Вход, а не двухтактный выход. AN4899 оговаривает, что 5 В допустимы на выводе в режиме входа. В той же заметке (раздел 5.3.3) STM32 работает на шине I²C с подтяжкой к 5 В: выводы I²C — с открытым стоком, транзистор P-MOS выключен, и к 5 В линию тянет внешний резистор.

Так STM32 с питанием 3,3 В напрямую работает с 5-вольтовыми устройствами: вход FT принимает их уровни, а высокий уровень выхода STM32 не ниже 2,4 В при токе 8 мА (таблица 37 DS5319, таблица 49 DS8626) и понятен любому входу с порогами ТТЛ — 0,8 и 2,0 В. У входа КМОП порог высокого уровня — около двух третей питания (AN4899, раздел 5.1.4), при 5 В это 3,3 В, а гарантированный высокий уровень STM32 при 8 мА — VDD − 0,4 = 2,9 В. Такому входу нужен открытый сток с подтяжкой к 5 В или преобразователь уровней.

Внешние прерывания

Любой вывод может вызвать прерывание через контроллер EXTI. Линий для выводов шестнадцать: линия n обслуживает вывод с номером n, а какой порт к ней подключён — A, B, C и так далее, — выбирается в регистрах AFIO_EXTICR у STM32F1 и SYSCFG_EXTICR у STM32F4. Отсюда ограничение: PA0 и PB0 не могут одновременно вызывать прерывания, а PA0 и PB1 — могут. Вывод при этом остаётся в режиме входа (RM0008, 9.1.3; RM0090, 8.3.8). Минимальная длительность импульса, который заметит EXTI, — 10 нс (DS5319, таблица 38; DS8626, таблица 50). Регистры описаны на страницах EXTI STM32F1 и STM32F4, а приоритеты прерываний считает калькулятор NVIC.

Блокировка настроек: LCKR

Регистр LCKR замораживает настройки выбранных выводов до следующего сброса: у STM32F1 — биты CRL и CRH, у STM32F4 — MODER, OTYPER, OSPEEDR, PUPDR, AFRL и AFRH (RM0090, 8.3.6). Данные — ODR и BSRR — продолжают работать. Блокировка защищает от ошибочного кода, который мог бы перенастроить, например, вывод управления силовым ключом. Она включается последовательностью записей в бит LCKK (бит 16) с одинаковой маской выводов в битах 0–15: запись 1, запись 0, запись 1, затем чтение — и необязательное второе чтение, которое покажет LCKK = 1, если блокировка сработала. Ошибка в последовательности её отменяет. Запись выполняется только целым словом.

/* Lock the configuration of PA2 and PA5 until the next reset */
uint32_t key = GPIO_LCKR_LCKK | GPIO_LCKR_LCK2 | GPIO_LCKR_LCK5;
GPIOA->LCKR = key;
GPIOA->LCKR = key & ~GPIO_LCKR_LCKK;
GPIOA->LCKR = key;
(void)GPIOA->LCKR;
if (GPIOA->LCKR & GPIO_LCKR_LCKK) {
    /* locked */
}

То же делает функция HAL_GPIO_LockPin.

Неиспользуемые выводы

Неподключённый вход в цифровом режиме ловит наводки, его триггер Шмитта переключается случайным образом и тратит ток. AN4899 (разделы 6.1 и 7.1) предлагает либо перевести такие выводы в аналоговый режим — у STM32F4 это MODER = 11, у STM32F1 — CNF = 00 и MODE = 00, — либо включить подтяжку, либо подключить вывод к земле на плате. Если устройство чувствительно к электростатике, надёжнее выход с низким уровнем. Выход с открытым стоком без нагрузки тоже лучше держать в нуле, а не в высокоимпедансном состоянии (раздел 6.4). Перед уходом в режимы пониженного потребления все линии нужно привести к определённым уровням — выходом или подтяжкой (раздел 7.4).

Примеры на CMSIS

Кнопка и светодиод на STM32F103. Светодиод на PC13 включён между питанием и выводом, кнопка на PA0 замыкает вывод на землю, поэтому у входа включена подтяжка вверх.

#include "stm32f1xx.h"

int main(void)
{
    /* Clock for ports A and C */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN;

    /* PC13: general-purpose push-pull output, 2 MHz (MODE13 = 10, CNF13 = 00) */
    GPIOC->CRH = (GPIOC->CRH & ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13)) | GPIO_CRH_MODE13_1;

    /* PA0: input with pull-up (MODE0 = 00, CNF0 = 10, ODR0 = 1 selects the pull-up) */
    GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0)) | GPIO_CRL_CNF0_1;
    GPIOA->BSRR = GPIO_BSRR_BS0;

    for (;;) {
        if (GPIOA->IDR & GPIO_IDR_IDR0)
            GPIOC->BSRR = GPIO_BSRR_BS13;   /* released: PC13 high, LED off */
        else
            GPIOC->BSRR = GPIO_BSRR_BR13;   /* pressed: PC13 low, LED on */
    }
}

Выход и альтернативная функция на STM32F407: PA5 — обычный выход, PA2 — передатчик USART2 на AF7.

#include "stm32f4xx.h"

void gpio_init(void)
{
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

    /* PA5: push-pull output, low speed, no pull (MODER5 = 01) */
    GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER5) | GPIO_MODER_MODER5_0;

    /* PA2: USART2_TX on AF7, push-pull, medium speed */
    GPIOA->MODER   = (GPIOA->MODER & ~GPIO_MODER_MODER2) | GPIO_MODER_MODER2_1;
    GPIOA->OSPEEDR = (GPIOA->OSPEEDR & ~GPIO_OSPEEDR_OSPEED2) | GPIO_OSPEEDR_OSPEED2_0;
    GPIOA->AFR[0]  = (GPIOA->AFR[0] & ~GPIO_AFRL_AFSEL2) | (7U << GPIO_AFRL_AFSEL2_Pos);

    GPIOA->BSRR = GPIO_BSRR_BS5;   /* PA5 high */
    GPIOA->BSRR = GPIO_BSRR_BR5;   /* PA5 low */
}

Каждая запись меняет только поля своего вывода, поэтому выводы отладчика PA13 и PA14 остаются на месте. Без включённого тактирования порта его регистры не настроятся: у STM32F1 порты тактируются от шины APB2 (биты IOPxEN в RCC_APB2ENR), у STM32F4 — от AHB1 (биты GPIOxEN в RCC_AHB1ENR). В HAL то же делают функции HAL_GPIO_Init, HAL_GPIO_WritePin и HAL_GPIO_ReadPin, а скорость задаётся константами GPIO_SPEED_FREQ_LOW, MEDIUM, HIGH и у STM32F4 — VERY_HIGH. У STM32F1 они соответствуют режимам 2, 10 и 50 МГц, то есть кодам MODE 10, 01 и 11.

Частые ошибки

  • Не включено тактирование порта — запись в регистры не действует, а вывод остаётся входом.
  • Перезаписан регистр порта A целиком — выводы PA13 и PA14 теряют функцию SWD, отладчик не подключается. Восстановить связь обычно помогает подключение с удержанием сброса.
  • Нагрузка на PC13–PC15 — больше 3 мА эти выводы не дают, и источником тока для светодиода служить не могут.
  • Внутренняя подтяжка вместо внешней на I²C — фронты в несколько микросекунд, шина работает нестабильно или не работает вовсе.
  • 5 В на вывод не FT, на вывод с включённой подтяжкой или на незапитанный микроконтроллер — ток через защитные диоды; предельный наведённый ток — 5 мА на вывод.
  • Переключение одного вывода через ODR в основном цикле и в прерывании — изменения теряются; используйте BSRR.
  • Вход АЦП не в аналоговом режиме — оба руководства требуют для входов АЦП и выходов ЦАП аналоговый режим (RM0008, 9.1.11; RM0090, 8.3.2).

Частые вопросы

Какой ток можно брать с вывода STM32?

Абсолютный максимум — 25 мА на вывод, а сумма токов всех выводов вместе с потреблением самого микроконтроллера не должна превышать 150 мА у STM32F103 и 240 мА у STM32F407 (DS5319, таблица 7; DS8626, таблица 12). Нормированные уровни даташит гарантирует при ±8 мА: низкий не выше 0,4 В, высокий не ниже VDD − 0,4 В; при ±20 мА — с запасом 1,3 В. Выводы PC13, PC14 и PC15 питаются через ключ и отдают не больше 3 мА.

Можно ли подавать 5 В на вход STM32?

Только на выводы с пометкой FT в таблице выводов даташита. У STM32F103 и STM32F407 вход FT выдерживает от −0,3 до 5,5 В при питании 2–3,6 В, если на выводе выключены внутренние подтяжки и вывод не в аналоговом режиме. Пока микроконтроллер не запитан, по AN4899 на вывод нельзя подавать больше 3,6 В. Обычные выводы выдерживают не больше VDD + 0,3 В.

Чем отличается двухтактный выход от открытого стока?

Двухтактный (push-pull) выход сам формирует оба уровня: единица включает транзистор P-MOS к VDD, ноль — N-MOS к земле. Открытый сток включает только N-MOS: ноль тянет линию к земле, единица отпускает её, и высокий уровень создаёт внешний резистор. Открытый сток нужен для шин с несколькими передатчиками, как I²C, и для подтяжки к другому напряжению.

Что значит скорость вывода 2, 10 и 50 МГц у STM32F1?

Это не частота переключения порта, а крутизна фронтов выходного каскада. По DS5319 (таблица 38) в режиме 2 МГц фронт длится до 125 нс, в режиме 10 МГц — до 25 нс, в режиме 50 МГц — 5–12 нс в зависимости от нагрузки. Чем быстрее фронт, тем сильнее импульсы тока и помехи, поэтому ST советует выбирать самую медленную скорость, которой хватает для сигнала.

Почему после перенастройки порта A пропадает отладчик?

Выводы PA13 и PA14 после сброса работают как SWDIO и SWCLK. У STM32F4 это видно в регистре GPIOA_MODER: после сброса в нём 0xA800 0000, то есть PA13, PA14 и PA15 в режиме альтернативной функции. Если записать в MODER значение целиком, а не изменить только нужные поля, SWD отключится. Меняйте регистр чтением-изменением-записью.

Как переключить вывод STM32 атомарно?

Записью в регистр BSRR: единица в бите n (0–15) устанавливает вывод n, единица в бите n + 16 сбрасывает его, нули ничего не меняют. Это одна запись по шине, прерывание её не разорвёт, и остальные выводы порта не затрагиваются. Так работают HAL_GPIO_WritePin и LL_GPIO_SetOutputPin. Если в одной записи заданы и установка, и сброс одного вывода, побеждает установка.

Источники

  1. STMicroelectronics. RM0008 Rev 21. Reference manual: STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx — 9.1 — режимы, структура вывода (рисунки 13–18), таблицы 20–21 — коды CNF и MODE, состояние после сброса и выводы JTAG; 9.1.11 — настройка выводов для периферии (таблицы 22–33); 9.2 — регистры GPIO, доступ только словами, приоритет установки в BSRR; 9.3 — PC14/PC15 и PD0/PD1 как GPIO, ремап; 9.4 — тактирование AFIO, поле SWJ_CFG; 31.4.4 — освобождение выводов JTAG
  2. STMicroelectronics. RM0090 Rev 22. Reference manual: STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 — 8.3 — режимы и таблица 36, выводы отладчика после сброса, мультиплексор AF0–AF15 (рисунок 26), BSRR, блокировка LCKR, аналоговый режим без устойчивости к 5 В; 8.4 — значения MODER, OSPEEDR и PUPDR после сброса; 9.1 — ячейка компенсации
  3. STMicroelectronics. DS5319 Rev 20. STM32F103x8, STM32F103xB datasheet — таблицы 6, 7 и 9 — предельные напряжения и токи, рабочий диапазон входов FT; таблица 35 — наведённый ток; таблица 36 — пороги, гистерезис, утечка, подтяжки; таблица 37 — выходные уровни при 8 и 20 мА; таблица 38 и рисунок 30 — частоты и фронты для MODE; ограничения PC13–PC15; выводы I²C — не «настоящий» открытый сток
  4. STMicroelectronics. DS8626 Rev 12. STM32F405xx, STM32F407xx datasheet — таблицы 11, 12 и 14 — предельные напряжения и токи, рабочий диапазон входов FT; таблица 48 — пороги, гистерезис, подтяжки (PA10 и PB12 — 7–14 кОм); таблица 49 — выходные уровни; таблица 50 — частоты и фронты для OSPEEDR, ячейка компенсации выше 50 МГц
  5. STMicroelectronics. AN4899 Rev 4. Guidelines for GPIO hardware settings and low-power consumption on STM32 MCUs, 2026 — 5.1.3 — динамический ток C·V·F, скорость на него не влияет; 5.1.4 — пороги КМОП и ТТЛ; 5.1.5 — время нарастания 0,8473·R·C; 5.2.2 — выводы FT: до VDD + 3,6 В и не выше 5,5 В, без питания — не выше 3,6 В; 5.3.3 — шина I²C 5 В; 6.1–6.6 — неиспользуемые выводы, открытый сток без нагрузки, подтяжки выводов отладчика; 7.1–7.4 — аналоговый режим для неиспользуемых выводов, выбор скорости
  6. NXP Semiconductors. UM10204: I2C-bus specification and user manual, Rev. 7.0, 1 October 2021 — наибольшее время нарастания фронта: 1000 нс в Standard-mode, 300 нс в Fast-mode
  7. STM32-base. STM32F103C8T6 Blue Pill — светодиод на PC13, включённый на втекающий ток
  8. STMicroelectronics. STM32CubeF1 и STM32CubeF4: драйверы HAL и LL, заголовки CMSIS (репозитории stm32f1xx-hal-driver, stm32f4xx-hal-driver, cmsis-device-f1, cmsis-device-f4) — HAL_GPIO_WritePin, HAL_GPIO_TogglePin и HAL_GPIO_LockPin в stm32f1xx_hal_gpio.c и stm32f4xx_hal_gpio.c; LL_GPIO_SetOutputPin и LL_GPIO_ResetOutputPin; константы GPIO_SPEED_FREQ_x; имена битов в stm32f103xb.h и stm32f407xx.h

Нашли ошибку?