Управление портами ввода-вывода через функции библиотеки HAL

Допустим, нам необходимо перенести нашу последнюю программу на другой микроконтроллер семейства STM32. Это потребует множества переписываний и изменений в коде, включая открытие технической документации, проверку имен и форматов, исправление ошибок и т.д. Однако, все эти трудности могут быть устранены с помощью библиотеки HAL, которая позволяет работать с понятными объектами вместо сложных регистров конфигурации. Изучим работу с портами GPIO и выводами портов, управление которыми не сложнее, чем в системе Arduino, за исключением большего количества режимов.

Постановка задачи

Необходимо установить конфигурацию выводов:

PB12 – Вход с подтягивающим на шину питания резистором. К нему у нас подключена кнопка.

PB13 – Активный выход. Мы подключили к нему светодиод.

PC13 – Активный выход. К нему подключен светодиод платы.

Реализовать алгоритм управления светодиодом от кнопки:

Кнопка нажата – светодиод светится;

Кнопка отжата – светодиод погашен.

Постановка задачи.

image

С помощью STM32CubeMX создадим проект Lesson8_1, в котором настроим только систему тактирования. Конфигурацию портов создавать нее будем. Сделаем это с помощью функций библиотеки HAL. Будем заполнять файл main.c постепенно.

Конфигурация портов с помощью библиотеки HAL.

Команды инициализации будем вставлять в блок

image

Файла maiv.c.

Если мы не разрешили тактирование портов в STM32CubeMX, то надо это сделать функцией __HAL_RCC_GPIOx_CLK_ENABLE().

Не будем вдаваться в подробности, просто выполним команды разрешения портов B и C.

__HAL_RCC_GPIOB_CLK_ENABLE(); // разрешение порта B

__HAL_RCC_GPIOC_CLK_ENABLE(); // разрешение порта C

Заходим в справочник по функциям HAL для управления портами и видим на первом месте функцию инициализации HAL_GPIO_Init.

Void HAL_GPIO_Init (GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_Init)

Функция имеет 2 аргумента:

GPIOx – это имя порта, с которым мы работаем. Указывается в общепринятом виде: GPIOA, GPIOB, GPIOC и т.д.

GPIO_Init – указатель на структуру параметров инициализации.

Структура описывается так:

image

Подробно назначение элементов структуры и варианты значений для них можно посмотреть в справочнике.

Для инициализации порта нам необходимо объявить структуру типа GPIO_InitTypeDef.

GPIO_InitTypeDef GPIO_InitStruct = {0};

Задаем нужные элементы структуры для вывода PB12.

image

Вызываем функцию HAL_GPIO_Init для порта B.

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

Делаем тоже самое для выводов PB13 и PC13.

Конфигурация портов с помощью библиотеки HAL.
image

Установка конфигурации наших трех выходов закончена.

Дальше нам необходимо считать состояние вывода PB12. К нему мы подключили кнопку.

Сделать это можно функцией HAL_GPIO_ReadPin.

Полный формат: GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin).

У функции 2 аргумента:

GPIOx – выбор порта (GPIOA, GPIOB, GPIOC … ).

Pin – номер вывода (GPIO_PIN_0 … GPIO_PIN_15).

Функция возвращает состояние вывода, которое может принимать 2 значения:

GPIO_PIN_SET – высокий уровень;

GPIO_PIN_RESET – низкий уровень.

Блок проверки состояния кнопки будет выглядеть так.

image

Вставляем его в программу, но уже в цикл while(1) перед завершением блока.

image

Теперь надо в зависимости от положения кнопки установить вывод PB13 (светодиод) в нужное состояние.

Для установки и сброса выводов портов есть функция HAL_GPIO_WritePin.

Формат: void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState).

Аргументы:

GPIOx – выбор порта (GPIOA, GPIOB, GPIOC … ).

Pin – номер вывода (GPIO_PIN_0 … GPIO_PIN_15).

PinState – состояние вывода:

GPIO_PIN_SET – высокий уровень;

GPIO_PIN_RESET – низкий уровень.

Чтобы зажечь светодиод надо вызвать функцию:

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET); // сброс вывода PB13

Погасить светодиод можно функцией:

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET); // установка вывода PB13

Вставляем эти команды в ветки оператора условного перехода.

image

Для обращения к кнопке, светодиоду мы использовали абсолютные имена – номера выводов, название портов. Это не совсем удобно.

Давайте создадим новый проект Lesson8_2. Настроим конфигурацию системы тактирования, назначим вывод PB12 на режим вход с подтягивающим к питанию резистором, определим вывод PB13, как активный вывод. И самое главное – присвоим им имена (User label) Button и Led.

Откроем новый проект. Заглянем в файл main.h.

image

Там вот такой блок.

image

STM32CubeMX сделал для кнопки 2 переназначения основных аргументов HAL-функций управления портами :

К имени вывода (Button) он добавил _Pin и присвоил стандартное название номера вывода GPIO_PIN_12.

К имени вывода (Button) он добавил _GPIO_Port и присвоил стандартное название порта GPIOB.

И такую же операцию конфигуратор совершил над именем светодиода (Led).

Теперь в функциях в качестве параметров мы можем использовать символьные имена, часть которых мы задали на этапе конфигурации с помощью STM32CubeMX.

С учетом этого наша конструкция в цикле while() будет выглядеть так:

image

Автор: Эдуард

Микроконтроллер STM32

Одна из линеек микроконтроллеров, которые производит компания STMicroelectronics.

Применяемость

Создана для широкого спектра применений, и применяются в различных областях, включая автоматизацию домашней электроники, транспортные средства, медицинские устройства, устройства IoT, промышленные автоматизированные системы и различные приборы и устройства.