Stm32. порты ввода/вывода
Микроконтроллеры Процессоры, проекты, программирование
Порты ввода/вывода GPIO в STM32 имеют по 16 линий, каждая из которых может быть настроена необходимым образом.
Поддерживаются функции цифрового ввода, цифрового вывода, входа внешнего прерывания, а также функции ввода/вывода других модулей микроконтроллера.
Программирование STM32 для работы с GPIO основано на использовании регистров конфигурации, чтения, записи, защиты конфигурации и регистра битового доступа.
Регистры конфигурации порта
Port configuration register low (GPIOx_CRL) (x=A..G)
Port configuration register high (GPIOx_CRH) (x=A..G)
Для программирования режимов работы портов ввода/вывода STM32, используются два 32 разрядных регистра для каждого GPIO. Они позволяют произвольно настроить режим работы любой отдельной линии.
Регистр GPIOx_CRL отвечает за линии с номерами от 0 до 7, GPIOx_CRH – за линии 8-15. Для каждой из них в регистре имеется два двухразрядных поля CNFy[1:0] и MODEy[1:0].
Первое определяет тип работы линии, второе – направление обмена по линии. все биты доступны для чтения/записи.
Регистр GPIOx_CRL
Бит регистра | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
Поле | CNF7[1:0] | MODE7[1:0] | CNF6[1:0] | MODE6[1:0] | CNF5[1:0] | MODE5[1:0] | CNF4[1:0] | MODE4[1:0] | ||||||||
Линия ввода/вывода | 7 | 6 | 5 | 4 | ||||||||||||
Бит регистра | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
Поле | CNF3[1:0] | MODE3[1:0] | CNF2[1:0] | MODE2[1:0] | CNF1[1:0] | MODE1[1:0] | CNF0[1:0] | MODE0[1:0] | ||||||||
Линия ввода/вывода | 3 | 2 | 1 |
Регистр GPIOX_CRH
Бит регистра | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
Поле | CNF15[1:0] | MODE15[1:0] | CNF14[1:0] | MODE14[1:0] | CNF13[1:0] | MODE12[1:0] | CNF12[1:0] | MODE12[1:0] | ||||||||
Линия ввода/вывода | 15 | 14 | 13 | 12 | ||||||||||||
Бит регистра | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
Поле | CNF11[1:0] | MODE11[1:0] | CNF10[1:0] | MODE10[1:0] | CNF9[1:0] | MODE9[1:0] | CNF8[1:0] | MODE8[1:0] | ||||||||
Линия ввода/вывода | 11 | 10 | 9 | 8 |
Поле MODEy[1:0] может принимать следующие значения:
- 00 – линия работает на ввод. Данное состояние устанавливается после сброса.
- 01 – линия работает на выход, с максимальной частотой переключения 10 МГц
- 10 – линия работает на выход, с максимальной частотой переключения 20 МГц
- 11 – линия работает на выход, с максимальной частотой переключения 50 МГц
Поле CNFy[1:0] зависит от направления передачи. При работе на вход (MODEy[1:0]=0) доступны следующие состояния:
- 00 – аналоговый вход.
- 01 – вход в третьем состоянии. (Устанавливается после сброса).
- 10 – вход с подтягивающим резистором
- 11 – зарезервировано для будущих применений.
При работе на выход (MODEy[1:0]>0) поле CNFy[1:0] может иметь следующие состояния:
- 00 – цифровой выход
- 01 – цифровой выход с открытым стоком
- 10 – цифровой выход, подключенный специализированным блокам
- 11 – цифровой выход, подключенный специализированным блокам с открытым стоком
Регистр защиты от изменения настроек
Port configuration lock register (GPIOx_LCKR) (x=A..G)
Бит | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
Поле | Резерв | LCKK | ||||||||||||||
Бит | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
Поле | LCK15 | LCK14 | LCK13 | LCK12 | LCK11 | LCK10 | LCK9 | LCK8 | LCK7 | LCK6 | LCK5 | LCK4 | LCK3 | LCK2 | LCK1 | LCK1 |
Установить блокируемый бит в GPIOx_LCKRДля невозможности изменения настроек порта в микроконтроллерах STM32 используется регистр GPIOx_LCKR. Его младщие 15 бит отвечают за соответсвующие линии порта ввода/вывода. Бит 16, установленный в 1, разрешает блокировку изменения настроек.
все биты доступны на чтение/запись. Для усложнения жизни пользователям 😉, используется специальный алгоритм установки защиты. Если он применен, то следующее изменение конфигурации доступно только после сброса.
Алгоритм установки защиты выглядит следующим образом:
- Установить бит 16 GPIOx_LCKR.
- Сбросить бит 16 GPIOx_LCKR.
- Установить бит 16 GPIOx_LCKR.
- Прочитать GPIOx_LCKR
- Повторно прочитать GPIOx_LCKR
Регистры установки состояния линий
В отличие от привычных 8-ми битных моделей, в STM32 имеется несколько регистров, отвечающих за состояние линий порта ввода вывода. Условно они разделены на две группы – регистры порта и регистры установки отдельных битов.
Выходной регистр порта ввода/вывода
Port output data register (GPIOx_ODR) (x=A..G)
Бит | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
Поле | Резерв | |||||||||||||||
Бит | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
Поле | ODR15 | ODR14 | ODR13 | ODR12 | ODR11 | ODR10 | ODR9 | ODR8 | ODR7 | ODR6 | ODR5 | ODR4 | ODR3 | ODR2 | ODR1 | ODR0 |
Данный регистр имеет разрядность 32, но используются только младшие 16 бит. Биты с 16 по 31 не используются. При записи в GPIOx_ODR какого-либо значения, это значение устанавливается на выходных линиях соответствующего порта. Биты регистра доступны только для чтения/записи.
Входной регистр
Port input data register (GPIOx_IDR) (x=A..G)
Бит31302928272625242322212019181716Бит1514131211109876543211
Поле | Резерв | |||||||||||||||
Поле | IDR15 | IDR14 | IDR13 | IDR12 | IDR11 | IDR10 | IDR9 | IDR8 | IDR7 | IDR6 | IDR5 | IDR4 | IDR3 | IDR2 | IDR1 | IDR0 |
Аналогично регистру выхода, регистр входа имеет толь 16 младших действующих бит из 32. Чтение GPIOx_IDR возвращает значение состояния всех линий порта. Биты регистра доступны только для чтения.
Регистр битовых операций
Port bit set/reset register (GPIOx_BSRR) (x=A..G)
Бит31302928272625242322212019181716Бит1514131211109876543211
Поле | BR15 | BR14 | BR13 | BR12 | BR11 | BR10 | BR9 | BR8 | BR7 | BR6 | BR5 | BR4 | BR3 | BR2 | BR1 | BR0 |
Поле | BS15 | BS14 | BS13 | BS12 | BS11 | BS10 | BS9 | BS8 | BS7 | BS6 | BS5 | BS4 | BS3 | BS2 | BS1 | BS0 |
Данный регистр позволяет обращаться к конкретной линии ввода вывода микроконтроллера STM32.
Запись единицы в один из старших разрядов сбрасывает выход линии, а запись единицы в младшие разряды устанавливает высокий уровень сигнала на соответствующей линии.
Запись в регистр производится в формате слова, при этом нулевые биты никакого действия не оказывают. Биты регистра доступны только для записи.
Регистр сброса
Port bit reset register (GPIOx_BRR) (x=A..G)
Бит31302928272625242322212019181716Бит1514131211109876543211
Поле | Резерв | |||||||||||||||
Поле | BR15 | BR14 | BR13 | BR12 | BR11 | BR10 | BR9 | BR8 | BR7 | BR6 | BR5 | BR4 | BR3 | BR2 | BR1 | BR0 |
Данный регистр производит сброс высокого уровня линии, установленной в регистре GPIOx_ODR. Задействованы только младшие 16 бит, доступных только для записи.
Еще по теме:
STM32. Работа с базовыми портами ввода/вывода. Примеры.
Первый проект на STM32 Discovery.
You have no rights to post comments
Источник: https://mcucpu.ru/index.php/stm32/82-stm32gpio
Изучаем STM32. Урок 2. Изучаем порты ввода-вывода GPIO (ч1) — DRIVE2
Добрый день, итак, пока есть время между редактированиями кодов и пайками)) напишу ещё одну статейку. На этот раз мы будем знакомиться с нашими ножками (нет не теми что внизу), а теми которые находятся на микроконтроллере и за счёт чего он воспринимает сигналы из внешнего мира и соответственно передаёт сигналы в него.
Итак, давайте посмотрим на блок — схему порта ввода-вывода контроллера
Тут у нас справа расположены защитные диоды, дальше внизу расположен регистр вывода и на нём мы видим два полевичка один из которых N-канаьный, второй P-канальный. Именно они нам выдают либо лог. единицу, либо лог. ноль.Вверху нарисован регистр ввода, в котором мы видим триггер шмидта, перед ним мы видим резисторы подтяжки
Ну кому более интересно это, тот может найти feference manual и выучить всё от корки до корки, мы же в данной части урока просто разберёмся что значат разные режимы работы наших портов
Итак, помните в прошлом уроке мы настраивали чем у нас будет ножка контроллера — Входом, Выходом. Но это не все параметры. Ещё ножка может быть сконфигурирована как аналоговый входвыход для допустим работы с АЦП, или с ЦАП, у кого он есть на “борту”))
Давайте рассмотрим все режимы работы
1)Input floating — по простому это вход безо всяких подтяжек (Hi-Z состояние, плавающий). По простому вход у нас ни к чему не подключён (привет помехи))))
2)Input pull-up — режим входа, в котором он чрез подтягивающий резистор подключён к питанию (номинал резистора несколько десятков килоОм)
3)Input-pull-down — режим входа, в котором он чрез подтягивающий резистор подключён к земле (массе) (номинал резистора несколько десятков килоОм)
4)Analog — режим работы, который включаем если желаем работать с АЦП или ЦАП
5)Output open-drain with pull-up or pull-down capability — выход с “открытым коллектором”
6)Output push-pull with pull-up or pull-down capability — самый используемый режим, в котором наш пин может выдавать как лог. ноль так и лог. единицу (это будут работать те самые полевые тарнзисторы о которых писал выше)
7)Alternate function push-pull with pull-up or pull-down capability — альтернативная функция (двухтактный вывод)
8)Alternate function open-drain with pull-up or pull-down capability — альтернативная функция (открытый
коллектор)
Теперь опишу как работаем с этими параметрами в нашей среде программирования.
Вот смотрите, кусочек кода, который отвечает за настройку параметров выхода
GPIO_InitStruct.Pin = GPIO_PIN_0; — данная строчка кода указывает что конфигурировать мы будем ножку 0
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; — Данная строчка указывает что режим работы — ВходУ данной строчки могут быть вот такие параметрыGPIO_MODE_INPUTGPIO_MODE_OUTPUT_PPGPIO_MODE_OUTPUT_ODGPIO_MODE_AF_PP
GPIO_MODE_AF_OD
Следующая строчка GPIO_InitStruct.Pull = GPIO_PULLDOWN; — Указывает что у нас подтяжка к массе. У данной строчки ещё могут быть вот такие вариантыGPIO_NOPULLGPIO_PULLUP
GPIO_PULLDOWN
Ну и последняя строчка указывает нам с каким портом нашего контроллера мы вообще только что разговаривали) — HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Здесь мы рассмотрели настройку нашего пина к которому подключена кнопка. PA0.
А давайте теперь рассмотрим настройку нашего порта, куда подключены светодиоды/*Configure GPIO pins : PD12 PD13 */GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_LOW;HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13; — эта строчка указывает какие пины настраиваем
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; — эта строка указыввает нам режим работы — ВЫХОД двухтактный (push-pull) . Возможные варианты конфигурации описаны чуть выше.
GPIO_InitStruct.Pull = GPIO_PULLUP; — данная штука указывает что включена подтяжка к питаниюВозможные варианты конфигурации описаны чуть выше.
Читайте также: Пожарный датчик задымления
GPIO_InitStruct.Speed = GPIO_SPEED_LOW; — данная строчка настраивает скорость работы выхода
Возможны вот такие вариантыGPIO_SPEED_LOW — низкая скорость 2MHzGPIO_SPEED_MEDIUM — средняя скорость 25MHzGPIO_SPEED_FAST — повышеная скорость 50MHz
GPIO_SPEED_HIGH -высокая скорость до 100MHz
Также, чтобы работал наш порт, и мы что то могли с ним делать — нам нужно включить тактирование порта.
Так как мы создаём проект в CubeMX, то он за нас это всё делает, но на будущее, мало ли, может кто то захочет использовать старые библиотеки- не забывайте подавать тактирование на нужные вам порты.
В нашем случае тактирование наших портов включается вот таким образом/* GPIO Ports Clock Enable */__GPIOA_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
Если поищем дальше, что обозначают эти строки то вот что найдём. Функция включения тактирования нашего порта A.#define __HAL_RCC_GPIOA_CLK_ENABLE() do { __IO uint32_t tmpreg; SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);/* Delay after an RCC peripheral clock enabling */ mpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);UNUSED(tmpreg);
} while(0)
Ну а теперь код, с помощью которого мы управляем нашими пинами. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9,GPIO_PIN_RESET); — сбрасывает пин в НОЛЬHAL_GPIO_WritePin(GPIOC, GPIO_PIN_9,GPIO_PIN_SET); — устанавливает пин в ЕДИНИЦУ
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9); — изменяет состояние пина на противоположное. Если было 0, то станет единица, и наоборот.
Ну и добавлю сюда ещё одну функцию — функция задержки Delay. Мы её часто использовали в CAVR, и тут она тоже есть. Задаётся она в милисекундах и выглядит вот так — HAL_Delay(100);
Это означает задержка в 100 милисекунд.
Можете теперь поиграться светодиодами на плате, выставив задержку и используя HAL_GPIO_TogglePin. Ваши светодиоды будут по очереди перемигиваться.
Жмём палец вверх, и читаем, читаем, читаем мануалы, и уже в голове придумываем что мы сделаем на STM32! STM — мечты сбываются)))
Ну и не забываем про хорошую музычку, да погромче! Пока писал — наслаждался вот этим шедевральным концертом. С ним как то и светодиоды по другому перемигиваются))
Источник: https://www.drive2.ru/b/2212642/
Программирование STM32. Часть 1. GPIO, порты ввода-вывода STM32
Недавно коллега меня подсадил на идею создания умного дома, я даже успел заказать себе десятки разных датчиков. Встал вопрос о выборе Микроконтроллера (далее МК) или платы. После некоторых поисков нашёл несколько вариантов.
Среди них были и Arduino (включая его клоны, один из которых себе заказал ради того, чтобы просто побаловаться) и Launchpad, но всё это избыточно и громоздко (хотя в плане программирования гораздо проще, но тему холиваров поднимать не буду, у каждого свои вкусы). В итоге решил определяться не с готовой платой, а взять только МК и делать всё с нуля.
В итоге выбирал между Atmel ATtiny (2313), Atmel ATmega (решил отказаться т.к. не смог найти за адекватные деньги), STM32 (Cortex на ядре ARM). С тинькой я уже успел побаловаться, так что взял себе STM32VL-Discovery. Это можно назвать вступлением к циклу статей по STM32.
Оговорюсь сразу, автором большинства этих статей буду являться не я, т.к. сам только познаю, здесь я публикую их в первую очередь для себя, чтоб удобнее было искать если что-то забуду. И так поехали!
Общие сведения
Микроконтроллеры семейства STM32 содержат в своём составе до семи 16-разрядных портов ввода-вывода c именами от PORTA до PORTG. В конкретной модели микроконтроллера без исключений доступны все выводы портов, общее количество которых зависит от типа корпуса и оговорено в DataSheet на соответствующее подсемейство.
Для включения в работу порта x необходимо предварительно подключить его к шине APB2 установкой соответствующего бита IOPxEN в регистре разрешения тактирования периферийных блоков RCC_APB2ENR:
RCC->APB2ENR |= RCC_APB2ENR_IOPxEN; // Разрешить тактирование PORTx.
Управление портами STM32 осуществляется при помощи наборов из семи 32-разрядных регистров:
- GPIOx_CRL, GPIOx_CRH – задают режимы работы каждого из битов порта в качестве входа или выхода, определяют конфигурацию входных и выходных каскадов.
- GPIOx_IDR – входной регистр данных для чтения физического состояния выводов порта x.
- GPIOx_ODR– выходной регистр осуществляет запись данных непосредственно в порт.
- GPIOx_BSRR – регистр атомарного сброса и установки битов порта.
- GPIOx_BSR – регистр сброса битов порта.
- GPIOx_LCKR – регистр блокировки конфигурации выводов.
Режимы работы выводов GPIO
Режимы работы отдельных выводов определяются комбинацией битов MODEy[1:0] и CNFy[1:0] регистров GPIOx_CRL и GPIOx_CRH (здесь и далее: x-имя порта, y- номер бита порта).
GPIOx_CRL — регистр конфигурации выводов 0…7 порта x:
Структура регистра GPIOx_CRH аналогична структуре GPIOx_CRL и предназначена для управления режимами работы старших выводов порта (биты 8…15).
Биты MODEy указанных регистров определяют направление вывода и ограничение скорости переключения в режиме выхода:
- MODEy[1:0] = 00: Режим входа (состояние после сброса);
- MODEy[1:0] = 01: Режим выхода, максимальная скорость – 10МГц;
- MODEy[1:0] = 10: Режим выхода, максимальная скорость – 2МГц;
- MODEy[1:0] = 11: Режим выхода, максимальная скорость – 50МГц.
Биты CNF задают конфигурацию выходных каскадов соответствующих выводов:
в режиме входа:
- CNFy[1:0] = 00: Аналоговый вход;
- CNFy[1:0] = 01: Вход в третьем состоянии (состояние после сброса);
- CNFy[1:0] = 10: Вход с притягивающим резистором pull-up (если PxODR=1) или pull-down (если PxODR=0);
- CNFy[1:0] = 11: Зарезервировано.
в режиме выхода:
- CNFy[1:0] = 00: Двухтактный выход общего назначения;
- CNFy[1:0] = 01: Выход с открытым стоком общего назначения;
- CNFy[1:0] = 10: Двухтактный выход с альтернативной функцией;
- CNFy[1:0] = 11: Выход с открытым стоком с альтернативной функцией.
С целью повышения помехоустойчивости все входные буферы содержат в своём составе триггеры Шмидта. Часть выводов STM32, снабженных защитными диодами, соединёнными с общей шиной и шиной питания, помечены в datasheet как FT (5V tolerant) — совместимые с напряжением 5 вольт.
Защита битов конфигурации GPIO
Для защиты битов в регистрах конфигурации от несанкционированной записи в STM32 предусмотрен регистр блокировки настроек GPIOx_LCKR
GPIOx_LCKR — регистр блокировки настроек вывода порта:
Для защиты настроек отдельного вывода порта необходимо установить соответствующий бит LCKy. После чего осуществить последовательную запись в разряд LCKK значений “1” — “0” — “1” и две операции чтения регистра LCKR, которые в случае успешной блокировки дадут для бита LCKK значения “0” и “1” . Защита настроечных битов сохранит своё действие до очередной перезагрузки микроконтроллера.
Файл определений для периферии микроконтроллеров STM32 stm32f10x.h определяет отдельные группы регистров, объединённые общим функциональным назначением (в том числе и GPIO), как структуры языка Си, а сами регистры как элементы данной структуры. Например:
GPIOC->BSRR – регистр BSRR установки/сброса порта GPIOC.
Воспользуемся определениями из файла stm32f10x.h для иллюстрации работы с регистрами ввода-вывода микроконтроллера STM32F100RB установленного в стартовом наборе STM32VLDISCOVERY:
#include “stm32F10x.h” u32 tmp; int main (void) { RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Разрешить тактирование PORTC. GPIOC->CRH |= GPIO_CRH_MODE8; // Вывод светодиода LED4 PC8 на выход. GPIOC->CRH &=~GPIO_CRH_CNF8; // Двухтактный выход на PC8. GPIOC->CRH |= GPIO_CRH_MODE9; // Вывод светодиода LED3 PC9 на выход. GPIOC->CRH &=~GPIO_CRH_CNF9; // Двухтактный выход на PC9. GPIOA->CRL&=~GPIO_CRL_MODE0; // Кнопка “USER” PA0 – на вход. // Заблокировать настройки выводов PC8, PC9. GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9| GPIO_LCKR_LCKK; GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9; GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9| GPIO_LCKR_LCKK; tmp=GPIOC->LCKR; tmp=GPIOC->LCKR; }
Запись и чтение GPIO
Для записи и чтения портов предназначены входной GPIOx_IDR и выходной GPIOx_ODR регистры данных.
Запись в выходной регистр ODR порта настроенного на вывод осуществляет установку выходных уровней всех разрядов порта в соответствии с записываемым значением. Если вывод настроен как вход с подтягивающими резисторами, состояние соответствующего бита регистра ODR активирует подтяжку вывода к шине питания (pull-up, ODR=1) или общей шине микроконтроллера (pull-down, ODR=0).
Чтение регистра IDR возвращает значение состояния выводов микроконтроллера настроенных как входы:
// Если кнопка нажата (PA0=1), установить биты порта C, иначе сбросить. if (GPIOA->IDR & GPIO_IDR_IDR0) GPIOC->ODR=0xFFFF; else GPIOC->ODR=0x0000;
Сброс и установка битов порта
Для атомарного сброса и установки битов GPIO в микроконтроллерах STM32 предназначен регистр GPIOx_BSRR.
Традиционный для архитектуры ARM способ управления битами регистров не требующий применения операции типа “чтение-модификация-запись” позволяет устанавливать и сбрасывать биты порта простой записью единицы в биты установки BS (BitSet) и сброса BR (BitReset) регистра BSRR. При этом запись в регистр нулевых битов не оказывает влияния на состояние соответствующих выводов.
GPIOx_BSRR – регистр сброса и установки битов порта:
GPIOC->BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9; // Зажечь LED4 (PC8), погасить LED3.
GPIOC->BSRR=GPIO_BSRR_BS9|GPIO_BSRR_BR8; // Зажечь LED3 (PC9), погасить LED4.
Альтернативные функции GPIO и их переназначение (remapping)
Практически все внешние цепи специального назначения STM32 (включая выводы для подключения кварцевых резонаторов, JTAG/SWD и так далее) могут быть разрешены на соответствующих выводах микроконтроллера, либо отключены от них для возможности их использования в качестве выводов общего назначения. Выбор альтернативной функции вывода осуществляется при помощи регистров с префиксом “AFIO”_.
Помимо этого регистры AFIO_ позволяют выбирать несколько вариантов расположения специальных функций на выводах микроконтроллера. Это в частности относится к выводам коммуникационных интерфейсов, таймеров (регистры AFIO_MAPR), выводам внешних прерываний (регистры AFIO_EXTICR) и т. д.
Подробнее смотрите документы “Reference manual” на соответствующую подгруппу микроконтроллеров.
Проекты к статье:
Для управления GPIO STM32 Вы можете применить макросы написанные как альтернативу далеко не оптимальным по мнению многих библиотекам от ST: gpio_emcu.h
Дополнительный материал:
Другие части
Источник: https://ergoz.ru/programmirovanie-stm32-chast-1-gpio-portyi-vvoda-vyivoda-stm32/
STM32. Урок 2. Порты ввода/вывода
Во втором уроке цикла, посвященного работе с микроконтроллерами STM32, речь пойдет о портах ввода/вывода.
Порты микроконтроллера позволяют взаимодействовать с внешними устройствами, начиная от светодиода и кнопки и заканчивая более сложными устройствами: дисплеями, GPS и GSM модемами и так далее.
Также порты позволяют организовать связь с другими устройствами, например с компьютером.
General Purpose Input/Output (GPIO). GPIO основной и часто применяемый способ связи с внешней средой. Порты могут работать в двух режимах: вход (прием сигнала) и выход (передача сигнала). Работают они только с логическими уровнями 0 (низкий уровень) или 1 (высокий уровень).
Например, если подключить к порту в режиме выхода светодиод, то при подаче сигнала высокого уровня светодиод будет светиться, а при подаче низкого – потухнет.
Если включить вывод в режим входа и подключить к нему кнопку, то с помощью микроконтроллера можно отслеживать ее состояние: нажатое или отпущенное.
По сути GPIO самый простой и примитивный способ организации работы с внешними устройствами, но использование обработки прерываний и таймеров значительно расширяет возможности. Речь о них пойдет немного позже.
Решим первую практическую задачу: управление светодиодами и считывание состояние кнопки.
Следует отметить очень важный момент – порты микроконтроллера могут выдать ток не более 20 мА. Хотя выдать он их может, но один раз и ненадолго, до хлопка и сизого дыма;). Для подключения более мощных нагрузок следует использовать силовые ключи.
Итак, начнем. Для работы возьмем плату STM32F4 Discovery. На ней изначально установлена пользовательская кнопка, подключенная к порту PA0 и 4 светодиода, подключенные к портам PD12-PD15.
Схема подключение кнопки и светодиодов показаны на рисунке.
Резистор R1 номиналом 10кОм – «подтяжка к земле», позволяет избежать ситуации, когда порт не подключен ни к «0», ни к «1» – этого необходимо избегать, а резистор решает эту проблему. Такую подтяжку можно включить и программно, но лучше обезопасить себя так.
Резисторы R2-R5 330Ом ограничивают ток, протекающий через светодиоды. Их можно выбрать в диапазоне от 200Ом до 1кОм, все зависит от необходимой яркости.
Теперь перейдем к написанию программы. В качестве среды разработки я использую CooCox. Среда бесплатная и, на мой взгляд, удобная. Как начинать в ней работать рассказывать не буду – в интернете по ней достаточно информации, для прошивки использую STM32 ST-LINK Utility.
Для начала включаем тактирование порта A, к которому подключена кнопка:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
Теперь нужно правильно сконфигурировать порт:
//Структура содержащая настройки порта
GPIO_InitTypeDef GPIO_InitStructure;
//задаем номер вывода, если кнопка подключена, например к 6 порту, то пишем GPIO_Pin_6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
//порт будет работать как цифровой вход
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
Существует несколько вариантов режима работы порта: GPIO_Mode_IN – цифровой вход; GPIO_Mode_OUT – цифровой выход; GPIO_Mode_AF – альтернативная функция (UART и т.д.);
GPIO_Mode_AN – аналоговый режим.
//включаем подтяжку к «земле»
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
Возможны следующие режимы «подтяжки»: GPIO_PuPd_NOPULL – без подтяжки, вывод «болтается в воздухе» GPIO_PuPd_UP – подтяжка к 3,3В
GPIO_PuPd_DOWN – подтяжка к «земле»
//вызов функции инициализации
GPIO_Init(GPIOA, &GPIO_InitStructure);
Теперь сконфигурируем выводы, к которым подключены светодиоды:
//Включаем тактирование порта D
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
//Выбираем нужные выводы
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
//Включаем режим выхода
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
//вызов функции инициализации
GPIO_Init(GPIOD, &GPIO_InitStructure);
Вот и все, порты сконфигурированы. Теперь напишем обработку в основном цикле программы:
while(1) { //Если кнопка нажата, то… if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) { GPIO_SetBits(GPIOD, GPIO_Pin_12); //Подаем «1» на PD12 delay(); //Функция задержки GPIO_SetBits(GPIOD, GPIO_Pin_13); //Подаем «1» на PD13 delay(); GPIO_SetBits(GPIOD, GPIO_Pin_14); //Подаем «1» на PD14 delay(); GPIO_SetBits(GPIOD, GPIO_Pin_15); //Подаем «1» на PD15 delay(); GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //Сбрасываем все пины в «0» delay(); } }
Вот и все, программа готова. Полная версия в архиве с проектом. Работа платы показана на видео.
Теперь подробнее об использованных функциях: GPIO_ReadInputDataBit – чтение состояния выбранного порта.
Синтаксис:
GPIO_ReadInputDataBit(GPIO_TypeDef GPIOx, uint16_t GPIO_Pin);
Где GPIOx – выбранный порт, GPIO_Pin – выбранный пин. Возвращает 0 или 1.
GPIO_SetBits и GPIO_ResetBits устанавливают или сбрасывают бит выбранного порта. Синтаксис:
GPIO_SetBits(GPIO_TypeDef GPIOx, uint16_t GPIO_Pin);
GPIO_ResetBits(GPIO_TypeDef GPIOx, uint16_t GPIO_Pin);
Где GPIOx – выбранный порт, GPIO_Pin – выбранный пин.
Вот собственно и все, что нужно знать для работы с цифровыми портами. Следующая статья будет посвящена работе с UART.
Прикрепленные файлы:
Источник: http://cxem.net/mc/mc196.php
STM32 с нуля. GPIO. Порты ввода-вывода
Доброго времени суток! Сегодня мы займемся изучением GPIO! И, в первую очередь, давайте посмотрим в каких режимах могут работать порты ввода-вывода в STM32F10x. А режимов этих существует море, а именно:
- Input floating
- Input pull-up
- Input-pull-down
- Analog
- Output open-drain
- Output push-pull
- Alternate function push-pull
- Alternate function open-drain
А если по-нашему, то при работе на вход:
- Вход – Hi-Z
- Вход – подтяжка вверх
- Вход – подтяжка вниз
- Вход – аналоговый
При работе порта на выход имеем следующие варианты:
- Выход – с открытым коллектором
- Выход – двухтактный
- Альтернативные функции – выход типа «с открытым коллектором»
- Альтернативные функции – двухтактный выход
Вот кстати документация на STM32F103CB –
В даташите есть внушительная таблица, в которой показано, какие альтернативные функции имеются у конкретного вывода.
Вот, например, выводы PA9, PA10:
В столбце Default видим, какие функции будут выполнять эти пины при их настройке для работы в режиме Alternative function.
То есть, настроив эти пины соответствующим образом они из просто PA9 и PA10 превратятся в Rx и Tx для USART1. А для чего же тогда столбец Remap? А это не что иное, как очень полезная функция ремаппинга портов.
Благодаря ремапу, Tx USARTA ’а, например, может переместится с пина PA9 на PB6. Довольно часто эта функция оказывается чертовски полезной.
Ну с режимами вроде бы все более-менее понятно, пришло время окинуть взором регистры, которыми управляются порты ввода-вывода.
Раз уж только что обсудили в каких режимах могут существовать выводы STM32F10x, сразу же давайте прошарим как же их можно собственно перевести в нужный режим. А для этого выделены аж два регистра – CRL и CRH.
В первом конфигурируются выводы от 0 до 7, во втором, соответственно от 8 до 15. Регистры, как вы помните, 32-разрядные. То есть на 8 выводов приходтся 32 бита – получается 4 бита на одну ножку.
Открываем даташит и видим:
Например, надо нам настроить ножку PB5. Идем в регистр GPIOB->CRL и выставляем сответствующие биты так как нам требуется (на картинке 32-х битный регистр CRL). Для PB5 это биты:
После восьмибиток может показаться все достаточно сложным и каким то корявым, но на самом деле реализовано все довольно изящно =). Посмотрим, что тут есть еще.
Выходной регистр GPIOx_ODR – напоминает регистр PORTx в AVR. Все что попадает в этот регистр сразу же попадает во внешний мир. Регистр 32-разрядный, а ножек всего 16. Как думаете, для чего используются оставшиеся 16? Все очень просто, биты регистра с 15 по 31 не используются вовсе )
Входной регистр GPIOx_IDR – аналог PINx в AVR. Структура его похожа на упомянутую структуру ODR. Все, что появляется на входе микроконтроллера, сразу же оказывается во входном регистре IDR.
Еще два полезных регистра GPIOx_BSSR и GPIOx_BRR. Они позволяют менять значения битов в регистре ODR напрямую, без использования привычных бит-масок. То есть, хочу я, например, выставить в единицу пятый бит ODR. Записываю единичку в пятый бит GPIOx_BSSR, и все, цель достигнута. Вдруг захотелось сбросить пятый бит ODR – единицу в 5 бит GPIOx_BRR и готово.
Итак, основные регистры рассмотрели, но, на самом-то деле, мы в наших примерах будем делать все иначе, используя Standard Peripheral Library. Так что лезем ковырять библиотеку. За GPIO в SPL отвечают файлы stm32f10x_gpio.h и stm32f10x_gpio.c. Открываем их оба и видим очень много непонятных цифр-букв-значков итд.
На самом деле, все очень просто и понятно. За конфигурацию портов отвечает структура GPIO_InitTypeDef.
typedef struct { uint16_t GPIO_Pin; // Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOSpeed_TypeDef GPIO_Speed; // Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOMode_TypeDef GPIO_Mode; // Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef; |
Видим, что структура имеет три поля: GPIO_PIN, GPIO_Speed и GPIO_Mode.
Нетрудно догадаться, что первая отвечает за номер ножки порта, которую мы хотим настроить, вторая – за скорость работы порта, ну и третья, собственно, за режим работы.
Таким образом, для настройки вывода нам всего лишь нужно объявить переменную типа структуры и заполнить ее поля нужными значениями. Все возможные значения полей тут же – в stm32f10x_gpio.h. Например,
typedef enum { GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_PP = 0x18 }GPIOMode_TypeDef; |
Все значения уже рассчитаны создателями SPL, так что для настройки какого-нибудь вывода для работы в режиме Output push-pull надо всего лишь в соответствующей структуре задать поле: GPIO_Mode = GPIO_Mode_Out_PP.
Ну вот, структура объявлена, поля заполнены как надо, что же дальше? Ведь мы всего лишь создали переменную. Причем тут регистры, микроконтроллеры и вообще электроника? Лезем в файл stm32f10x_gpio.c и находим там тучу различных функций для работы с STM32 GPIO.
Рассмотрим функцию GPIO_Init() (код приводить не буду, все в файле библиотеки). Так вот, эта функция как раз и связывает нашу созданную структуру и конкретные регистры контроллера. То есть мы передаем в эту функцию переменную, в соответствии с которой выставляются нужные биты нужных регистров микроконтроллера.
Все очень просто, но от этого не менее гениально. Поковыряйте еще файлы библиотеки. Там функции на любой случай есть ) Кстати очень удобно – перед функцией идет описание переменных, которые она принимает и возвращает, а также описание собственно того, что эта функция призвана делать.
Так что, разобраться несложно, но надо немного дружить с английским. Хотя без этого никуда;)
Отвлечемся ненадолго от портов ввода-вывода и обсудим один довольно тонкий момент. Чтобы использовать порты, либо любую другую периферию, ОБЯЗАТЕЛЬНО надо включить тактирование.
И порты, и периферия изначально отключены от тактирования, так что без этого действия ничего не заведется. Программа скомпилируется, но на деле работать ничего не будет. За тактирование в SPL отвечают файлы stm32f10x_rcc.
c и stm32f10x_rcc.h. Не забывайте добавлять их в проект.
Давайте уже перейдем к программированию. Как это принято, заставим диодик помигать ) Чтобы получше разобраться с Standard Peripheral Library немножко усложним обычное мигание диодом – будем опрашивать кнопку, и если она нажата – диод загорается, иначе – гаснет.
Запускаем Keil, создаем проект, добавляем все нужные файлы, не забываем про CMSIS. Из SPL для этого проекта нам понадобятся 4 файла, уже упомянутые выше. Создание нового проекта описано в предыдущей статье учебного курса.
Также там можно найти ссылки на библиотеки )
Итак, код:
/****************************gpio.c*********************************/ //Подключаем все нужные файлы #include “stm32f10x.h” #include “stm32f10x_rcc.h” #include “stm32f10x_gpio.h” /*******************************************************************/ //Тут будет вся инициализация всей использующейся периферии void initAll() { //Объявляем переменную port типа GPIO_InitTypeDef GPIO_InitTypeDef port; //Это функция из файла stm32f10x_rcc.c, включает тактирование на GPIOA //GPIOA сидит на шине APB2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Про эту функцию напишу чуть ниже GPIO_StructInit(&port); //Заполняем поля структуры нужными значениями //Первый вывод – вход для обработки нажатия кнопки – PA1 port.GPIO_Mode = GPIO_Mode_IPD; port.GPIO_Pin = GPIO_Pin_1; port.GPIO_Speed = GPIO_Speed_2MHz; //А про эту функцию мы уже говорили //Отметим только что один из параметров – указатель(!) на //нашу структуру GPIO_Init(GPIOA, &port); //Настраиваем вывод, на котором будет висеть диодик – PA0 port.GPIO_Mode = GPIO_Mode_Out_PP; port.GPIO_Pin = GPIO_Pin_0; port.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &port); } /*******************************************************************/ int main() { //Объявляем переменную для хранения состояния кнопки uint8_t buttonState = 0; initAll(); while(1) { //С помощью функции из SPL считываем из внешнего мира //состояние кнопки buttonState = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); if (buttonState == 1) { GPIO_SetBits(GPIOA, GPIO_Pin_0); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_0); } } } /****************************End of file****************************/ |
Кстати, возможно кто-то обратит внимание на наличие скобок { }, несмотря на всего лишь одну инструкцию в теле if и else. А это уже привычка) Очень рекомендуется так писать, особенно при разработке крупных проектов.
При дописывании/исправлении программы невнимательный программист может не обратить внимания на отсутствие скобок и дописать вторую инструкцию, которая, как вы понимаете, уже окажется все блока if или else. Та же тема с циклами.
Когда над проектом работает много народу, нет никаких гарантий, что кто-нибудь не окажется невнимательным, так что, чтобы не тратить минуты/часы на последующие поиски косяка, рекомендую ставить эти скобки всегда ) Хотя может, кто-то и не согласится с такой логикой.
Нажимаем F7, компилируем, и вот наша первая программа для STM готова. Вроде бы код довольно подробно откомментирован, так что поясню только пару моментов.
Функция GPIO_StructInit(&port) – принимает в качестве аргумента адрес переменной port.
Эта функция заполняет поля структуры, переданной ей в качестве аргумента дефолтными значениями. Это делать не обязательно, но во избежание каких-нибудь непредсказуемых косяков, лучше всегда вызывать эту функцию.
Еще две функции, которые мы использовали:
- GPIO_SetBits(GPIOA, GPIO_Pin_0);
- GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Ну вы и так догадались для чего они
Источник: https://microtechnics.ru/stm32-uchebnyj-kurs-gpio-porty-vvoda-vyvoda/
STM32F1. Часть 1. GPIO, порты ввода-вывода STM32
ПодробностиКатегория: STM32F1 Cortex M3Опубликовано 09.12.2010 22:00Микроконтроллеры семейства STM32 содержат в своём составе до семи 16-разрядных портов ввода-вывода c именами от PORTA до PORTG.
В конкретной модели микроконтроллера без исключений доступны все выводы портов, общее количество которых зависит от типа корпуса и оговорено в DataSheet на соответствующее подсемейство.
Для включения в работу порта x необходимо предварительно подключить его к шине APB2 установкой соответствующего бита IOPxEN в регистре разрешения тактирования периферийных блоков RCC_APB2ENR:
RCC->APB2ENR |= RCC_APB2ENR_IOPxEN; // Разрешить тактирование PORTx.
Управление портами STM32 осуществляется при помощи наборов из семи 32-разрядных регистров:
GPIOx_CRL, GPIOx_CRH – задают режимы работы каждого из битов порта в качестве входа или выхода, определяют конфигурацию входных и выходных каскадов.
GPIOx_IDR – входной регистр данных для чтения физического состояния выводов порта x.
GPIOx_ODR – выходной регистр осуществляет запись данных непосредственно в порт.
GPIOx_BSRR – регистр атомарного сброса и установки битов порта.
GPIOx_BSR – регистр сброса настроек битов порта.
GPIOx_LCKR – регистр блокировки конфигурации выводов.
§ | Режимы работы выводов GPIO |
Режимы работы отдельных выводов определяются комбинацией битов MODEy[1:0] и CNFy [1:0] регистров GPIOx_CRL и GPIOx_CRH (здесь и далее: x-имя порта, y- номер бита порта). GPIOx_CRL – регистр конфигурации выводов 0…7 порта x:
Структура регистра GPIOx_CRH аналогична структуре GPIOx_CRL и предназначена для управления режимами работы старших выводов порта (биты 8…15). Биты MODEy указанных регистров определяют направление вывода и ограничение скорости переключения в режиме выхода:MODEy[1:0] = 00 – Режим входа (состояние после сброса); MODEy[1:0] = 01 – Режим выхода, максимальная скорость – 10МГц; MODEy[1:0] = 10 – Режим выхода, максимальная скорость – 2МГц;
MODEy[1:0] = 11 – Режим выхода, максимальная скорость – 50МГц.
Биты CNF задают конфигурацию выходных каскадов соответствующих выводов: в режиме входа:CNFy[1:0] = 00: Аналоговый вход; CNFy[1:0] = 01: Вход в третьем состоянии (состояние после сброса); CNFy[1:0] = 10: Вход с притягивающим резистором pull-up (если PxODR=1) или pull-down (если PxODR=0);
CNFy[1:0] = 11: Зарезервировано.
в режиме выхода:CNFy[1:0] = 00: Двухтактный выход общего назначения; CNFy[1:0] = 01: Выход с открытым стоком общего назначения; CNFy[1:0] = 10: Двухтактный выход с альтернативной функцией;
CNFy[1:0] = 11: Выход с открытым стоком с альтернативной функцией.
С целью повышения помехоустойчивости все входные буферы содержат в своём составе триггеры Шмидта. Часть выводов STM32, снабженных защитными диодами, соединёнными с общей шиной и шиной питания, помечены в datasheet как FT (5V tolerant) – совместимые с напряжением 5 вольт.
§ | Защита битов конфигурации GPIO |
Для защиты битов в регистрах конфигурации от несанкционированной записи в STM32 предусмотрен регистр блокировки настроек GPIOx_LCKR: GPIOx_LCKR – регистр блокировки настроек вывода порта x:Для защиты настроек отдельного вывода порта необходимо установить соответствующий бит LCKy. После чего осуществить последовательную запись в разряд LCKK значений “1” – “0” – “1” и две операции чтения регистра LCKR, которые в случае успешной блокировки дадут для бита LCKK значения “0” и “1” . Защита настроечных битов сохранит своё действие до очередной перезагрузки микроконтроллера. Файл определений для периферии микроконтроллеров STM32 stm32f10x.h определяет отдельные группы регистров, объединённые общим функциональным назначением (в том числе и GPIO), как структуры языка Си, а сами регистры как элементы данной структуры. Например: GPIOC->BSRR – регистр BSRR установки/сброса порта GPIOC. Воспользуемся определениями из файла stm32f10x.h для иллюстрации работы с регистрами ввода-вывода микроконтроллера STM32F100RB установленного в стартовом наборе STM32DISCOVERY:#include “stm32F10x.h” u32 tmp; int main (void) { RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Разрешить тактирование PORTC. GPIOC->CRH |= GPIO_CRH_MODE8; // Вывод светодиода LED4 PC8 на выход. GPIOC->CRH &=~GPIO_CRH_CNF8; // Двухтактный выход на PC8. GPIOC->CRH |= GPIO_CRH_MODE9; // Вывод светодиода LED3 PC9 на выход. GPIOC->CRH &=~GPIO_CRH_CNF9; // Двухтактный выход на PC9. GPIOA->CRL&=~GPIO_CRL_MODE0; // Кнопка “USER” PA0 – на вход. // Заблокировать настройки выводов PC8, PC9. GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9|GPIO_LCKR_LCKK; GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9; GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9|GPIO_LCKR_LCKK; tmp=GPIOC->LCKR; tmp=GPIOC->LCKR;
}
Для записи и чтения портов предназначены входной GPIOx_IDR и выходной GPIOx_ODR регистры данных. Запись в выходной регистр ODR порта настроенного на вывод осуществляет установку выходных уровней всех разрядов порта в соответствии с записываемым значением.
Если вывод настроен как вход с подтягивающими резисторами, состояние соответствующего бита регистра ODR активирует подтяжку вывода к шине питания (pull-up, ODR=1) или общей шине микроконтроллера (pull-down, ODR=0).
Чтение регистра IDR возвращает значение состояния выводов микроконтроллера настроенных как входы:
// Если кнопка нажата (PA0=1), установить биты порта C, иначе сбросить.
if (GPIOA->IDR & GPIO_IDR_IDR0) GPIOC->ODR=0xFFFF; else GPIOC->ODR=0x0000;
§ | Сброс и установка битов порта |
Для атомарного сброса и установки битов GPIO в микроконтроллерах STM32 предназначен регистр GPIOx_BSRR. Традиционный для архитектуры ARM способ управления битами регистров не требующий применения операции типа “чтение-модификация-запись” позволяет устанавливать и сбрасывать биты порта простой записью единицы в биты установки BS (BitSet) и сброса BR (BitReset) регистра BSRR. При этом запись в регистр нулевых битов не оказывает влияния на состояние соответствующих выводов. GPIOx_BSRR – регистр сброса и установки битов порта:
GPIOC->BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9; // Зажечь LED4 (PC8), погасить LED3.
GPIOC->BSRR=GPIO_BSRR_BS9|GPIO_BSRR_BR8; // Зажечь LED3 (PC9), погасить LED4.
§ | Альтернативные функции GPIO и их переназначение (remapping) |
Практически все внешние цепи специального назначения STM32 (включая выводы для подключения кварцевых резонаторов, JTAG/SWD и так далее) могут быть разрешены на соответствующих выводах микроконтроллера, либо отключены от них для возможности их использования в качестве выводов общего назначения. Выбор альтернативной функции вывода осуществляется при помощи регистров с префиксом “AFIO_”. Помимо этого регистры AFIO_ позволяют выбирать несколько вариантов расположения специальных функций на выводах микроконтроллера. Это в частности относится к выводам коммуникационных интерфейсов, таймеров (регистры AFIO_MAPR), выводам внешних прерываний (регистры AFIO_EXTICR) и т. д. Подробнее смотрите документы “Reference manual” на соответствующую подгруппу микроконтроллеров.
§ | Макросы управления портами, проекты к статье |
Не хочется критиковать стандартную библиотеку «STM32F10x Standard Peripherals Library» от STM, ведь то, что она есть – уже хорошо. Но некоторые операции с использованием её функций кажутся слишком громоздкими.
В качестве альтернативы вы можете использовать простые и эффективные макросы, написанные мной для управления портами STM32F1 ⇒ gpio_emcu.zip
Проекты к статье:
µVision 4.13a ⇒ STM32GPIO_emcu_uV.rar
IAR ARM 6.0 ⇒ STM32GPIO_emcu_iar.rar
IAR ARM 6.21 ⇒ STM32GPIO_emcu_iar_V6.21.rar
Далее ⇒ Часть 2. Система тактирования STM32.
Источник: http://eugenemcu.nichost.ru/articles/stm32f1/126-stm32-gpio