STM32F103C8T6 · МПС · лабораторная 1
Откуда берётся 0x4001 0C10 и почему запись именно по этому адресу зажигает светодиод на PB15. Пять уровней: от четырёх гигабайт адресного пространства до одного бита.
Уровень 1 · всё адресное пространство
У Cortex-M3 адреса 32-битные, то есть пространство от 0x00000000 до 0xFFFFFFFF — 4 ГБ. Памяти столько нет и близко: пространство поделено на области, и большинство адресов ни к чему не ведут. Периферия живёт в своей области, начиная с 0x40000000.
Важно понимать: это не «память, где лежат регистры». Никакой памяти по адресу 0x40010C10 нет. Там сидит схема, которая слушает шину: увидела запись по своему адресу — переключила транзисторы на выводе. Приём называется «отображение периферии на память» и позволяет управлять железом обычными командами LDR и STR.
Уровень 2 · внутри периферии
Периферия разложена по шинам. Медленная APB1 и быстрая APB2 отличаются предельной частотой (36 и 72 МГц), и у каждой свой кусок адресов. Порты GPIO сидят на APB2 — поэтому их тактирование включается в регистре RCC_APB2ENR.
0x4001, — это APB2.Уровень 3 · блоки на шине
Внутри APB2 блоки разложены по фиксированным смещениям, по 1 КБ адресов на блок. Отсюда «круглые» адреса портов.
SWJ_CFG = 010 в 0x4001 0004.Уровень 4 · регистры блока
Внутри килобайта, отведённого порту, заняты первые 28 байт — семь регистров подряд. Адрес регистра складывается из базы порта и смещения.
| Смещение | Регистр | Доступ | Что делает | Адрес в GPIOB |
|---|---|---|---|---|
| +0x00 | CRL | чтение и запись | режимы пинов 0–7 | 0x4001 0C00 |
| +0x04 | CRH | чтение и запись | режимы пинов 8–15 | 0x4001 0C04 |
| +0x08 | IDR | только чтение | уровни на выводах | 0x4001 0C08 |
| +0x0C | ODR | чтение и запись | что выдаём; во входном режиме — направление подтяжки | 0x4001 0C0C |
| +0x10 | BSRR | только запись | установить и сбросить биты ODR одной командой | 0x4001 0C10 |
| +0x14 | BRR | только запись | только сбросить | 0x4001 0C14 |
| +0x18 | LCKR | чтение и запись | заморозить настройку до перезагрузки | 0x4001 0C18 |
Смещения кратны четырём, потому что регистр — это 32-битное слово, а слово занимает 4 байта. Обращаться к нему нужно целиком: адреса «половины регистра» не существует.
Уровень 5 · биты внутри регистра
Ниже адресов начинаются биты. Как пин раскладывается по разрядам, зависит от регистра.
| Регистр | Сколько разрядов на пин | Где искать пин n |
|---|---|---|
| CRL / CRH | 4 | CRL для пинов 0–7, сдвиг 4·n; CRH для 8–15, сдвиг 4·(n−8). Внутри тетрады: старшие два бита CNF, младшие два MODE |
| IDR, ODR | 1 | бит n; старшая половина слова не используется |
| BSRR | 2 | бит n устанавливает, бит n+16 сбрасывает |
| BRR | 1 | бит n сбрасывает |
Четыре бита на пин в CRL и CRH — это не прихоть: режимов восемь, и двух битов на них не хватило бы. 16 пинов по 4 бита дают 64 бита, в одно слово не помещаются, поэтому регистра два.
Сборка
Выбери порт, регистр и пин — страница покажет, из чего складывается адрес и какие разряды отвечают за этот вывод. По умолчанию открыт синий канал твоего варианта: PB15 через BSRR.
Вариант 8
Светодиод с общим катодом: R = PA7, G = PB3, B = PB15. Кнопки: PA3, PA10, PB5, все с высоким уровнем при нажатии.
| Вывод | Роль | Регистр режима | Адрес | Разряды | BSRR: вкл / выкл |
|---|---|---|---|---|---|
| PA7 | красный | GPIOA_CRL | 0x4001 0800 | 31…28 | 1<<7 / 1<<23 |
| PB3 | зелёный | GPIOB_CRL | 0x4001 0C00 | 15…12 | 1<<3 / 1<<19 |
| PB15 | синий | GPIOB_CRH | 0x4001 0C04 | 31…28 | 1<<15 / 1<<31 |
| PA3 | кнопка 1 | GPIOA_CRL | 0x4001 0800 | 15…12 | подтяжка вниз: BR3 |
| PA10 | кнопка 2 | GPIOA_CRH | 0x4001 0804 | 11…8 | подтяжка вниз: BR10 |
| PB5 | кнопка 3 | GPIOB_CRL | 0x4001 0C00 | 23…20 | подтяжка вниз: BR5 |
Проверка
Адреса не абстрактные: их можно прочитать отладчиком, пока плата работает. С подключённым ST-Link:
Первое значение — GPIOB_CRL, режимы пинов 0–7. После сброса там 0x44444444: все восемь пинов вход без подтяжки, по цифре 4 на каждый. Второе — GPIOB_ODR, там нули. Запустишь программу лабы — цифры поменяются, и это лучший способ убедиться, что маски посчитаны верно.
RCC_APB2ENR не включён бит порта, чтение вернёт нули, а запись пропадёт бесследно. Регистр тактирования лежит по адресу 0x4002 1018 — уже не на APB2, а в блоке RCC на шине AHB.