
В STM32F10x имеется возможность использования различных режимов работы портов ввода-вывода. В настоящее время доступно множество таких режимов, а именно:
То есть при работе на вход:
При работе порта на выход имеем следующие варианты:
На сайте доступна документация для микроконтроллера STM32F103CB, которая содержит таблицу с описанием альтернативных функций для каждого вывода микроконтроллера. Ссылку на документацию можно добавить отдельным предложением. Документацию можно найти по этой ссылке: STM32F103CB datasheet. Вот, например, выводы 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 это биты:

После 8-битных контроллеров все это может показаться сложным и нелогичным, но на самом деле реализовано все довольно изящно. Посмотрим, что тут есть еще...
Итак, основные регистры рассмотрели, но, на самом-то деле, мы в наших примерах будем делать все иначе, используя Standard Peripheral Library. Так что идем изучать библиотеку.
За GPIO в SPL отвечают файлы stm32f10x_gpio.h и stm32f10x_gpio.c.За конфигурацию портов отвечает структура GPIO_InitTypeDef:

Видим, что структура имеет три поля: GPIO_PIN, GPIO_Speed и GPIO_Mode. Нетрудно догадаться, что первая отвечает за номер ножки порта, которую мы хотим настроить, вторая – за скорость работы порта, ну и третья, собственно, за режим. Таким образом, для настройки вывода нам всего лишь нужно объявить переменную типа GPIO_InitTypeDef и заполнить ее поля нужными значениями. Все возможные значения полей тут же – в stm32f10x_gpio.h. Например,

Все значения уже рассчитаны создателями SPL, так что для настройки какого-нибудь вывода для работы в режиме Output push-pull надо всего лишь в соответствующей структуре задать поле: GPIO_Mode = GPIO_Mode_Out_PP.
Ну вот, структура объявлена, поля заполнены как надо, что же дальше? Ведь мы всего лишь создали переменную. Причем тут регистры, микроконтроллеры и вообще электроника? Лезем в файл stm32f10x_gpio.c и находим там множество различных функций для работы с GPIO.
Рассмотрим функцию GPIO_Init() (код приводить не буду, все в файле библиотеки). Так вот, эта функция как раз и связывает нашу созданную структуру и конкретные регистры контроллера. То есть мы передаем в эту функцию переменную, в соответствии с которой выставляются нужные биты нужных регистров микроконтроллера.
Отвлечемся ненадолго от портов ввода-вывода и обсудим один довольно тонкий момент. Чтобы использовать порты, либо любую другую периферию, обязательно надо включить тактирование. И порты, и периферия изначально отключены от тактирования, так что без этого действия ничего не заведется. Программа скомпилируется, но на деле работать ничего не будет. За тактирование в SPL отвечают файлы stm32f10x_rcc.c и stm32f10x_rcc.h. Не забывайте добавлять их в проект.
Перейдем к программированию, заставим диод помигать Чтобы лучше разобраться с Standard Peripheral Library немножко усложним обычное мигание диодом – будем опрашивать кнопку, и если она нажата – диод загорается, иначе – гаснет. Запускаем Keil, создаем проект, добавляем все нужные файлы, не забываем про CMSIS. Из SPL для этого проекта нам понадобятся 4 файла, уже упомянутые выше. Создание нового проекта описано в предыдущей статье учебного курса и также там можно найти ссылки на библиотеки.

Функция GPIO_StructInit(&port) – принимает в качестве аргумента указатель на переменную port. Эта функция заполняет поля структуры, переданной ей в качестве аргумента значениями по умолчанию.
Еще две функции, которые мы использовали:
Автор: Aveal