6 в чем отличия драйвера hal от драйвера ll

Обновлено: 07.07.2024

LessonSTM

В уроке узнаем, что такое библиотека LL. Как ее использовать совместно с библиотекой HAL. Научимся управлять портами через функции LL.

Компания STMicroelectronics – производитель микроконтроллеров STM32 достойно поддерживает свою продукцию со стороны программного обеспечения. Один из ее программных продуктов – это пакет STMCube, значительно облегчающий труд разработчиков.

Сейчас в пакете нас интересуют:

  • STM32CubeMX – графический редактор конфигурации микроконтроллера, генератор начального кода.
  • Библиотека HAL – драйверы периферии высокого уровня абстракции.
  • Библиотека LL – низкоуровневые драйверы.

С первыми двумя компонентами мы познакомились в предыдущих уроках. В этом будем разбираться с третьим.

Библиотека LL.

HAL-драйверы ориентированы не на периферийные устройства микроконтроллера, а на функциональные возможности этих устройств. К примеру, на одном и том же таймере могут быть реализованы: отсчет интервалов времени, циклическое прерывание, ШИМ, захват и т.п. Для всех этих функций существуют разные драйверы HAL. Более того, один драйвер часто использует несколько периферийных устройств. Например, вместе с тем же таймером HAL-драйвер может управлять и системой прерываний.

Как следствие, HAL-драйверами можно пользоваться, не вникая в детали работы периферийных устройств. Они значительно облегчают труд разработчика.

Драйверы LL обеспечивают элементарные операции с регистрами периферии микроконтроллера. Их функции в точности повторяют возможные действия с регистрами. По сути это те же операции с именами библиотеки CMSIS, только используется не прямой доступ к регистрам, а функции. И данные для конфигурации задаются не в числовой форме, а в виде символьных констант.

Конечно, это облегчает работу по конфигурации периферии. Нет необходимости разбираться с форматами регистров, думать, в каком разряде надо выставить 0 или 1. Но знать назначение каждого регистра и принцип действия периферийного устройства в целом надо досконально.

Зато, в отличие от HAL-драйверов, функции библиотеки LL имеют намного меньший размер кода, выполняются значительно быстрее.

  • HAL- это высокоуровневые драйверы, ориентированные на функциональные возможности периферии. Они скрывают от программиста структуру периферийных устройств, значительно облегчают работу с ними. Также HAL-драйверы обеспечивают переносимость программного обеспечения на различные типы микроконтроллеров STM32.
  • LL – это драйверы низкого уровня, ориентированные на регистры. Их функции точно отражают структуру периферийных устройств на уровне регистров. Использование LL-драйверов требует глубокого знания периферии.

HAL и LL уровни дополняют друг друга и могут использоваться совместно. Все зависит от задачи, цели, по которой происходит оптимизация программы.

Порты ввода-вывода один из немногих видов периферийных устройств, работа с которыми через LL-функции скорее проще, чем с помощью HAL-драйверов. Не надо создавать дополнительную структуру, заполнять ее, понятно, что делает каждая функция.

Да и вообще, неумение пользоваться LL-библиотекой обязательно ограничит ваши возможности, как программиста STM32. Давайте учиться пользоваться LL-функциями.

Реализуем ту же задачу, что и в двух предыдущих уроках. Нажали кнопку – светодиод светится, отпустили – светодиод погас.

Совместное использование библиотек HAL и LL.

Для совместного использования библиотек необходимо выполнить ряд формальных действий. Возможно, есть какой-то другой способ, но я это делаю так.

Давайте создадим очередной учебный проект Lesson9_1. В STM32CubeMX зададим конфигурацию только системы тактирования на максимальную частоту 72 мГц. Выводы конфигурировать не будем.

Если в менеджере проектов (Project Manager) мы нажмем закладку Advanced setting в левом поле, то увидим окно расширенных установок.

STM32CubeMX

В верхнем поле указаны периферийные устройства, которые мы конфигурировали и напротив их выбрана библиотека HAL. Правой кнопкой мыши можно открыть выпадающее меню и установить библиотеку LL.

Если мы сделаем это, то код начальной конфигурации будет создан с использованием библиотеки LL. Конфигуратор установит для программы LL-драйверы.

Загрузка файлов в проект

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

Теперь нужно установить нужные нам LL-драйверы.

Сначала загрузим их по ссылке:

Для нашего микроконтроллера STM32F103T8C6 выберем STM32CubeF1.

Загрузка файлов

Нажмем Get Software и загрузим пакет STM32CubeF1.

Мы собираемся работать с портами ввода-вывода. Нам необходим драйвер stm32f1xx_ll_gpio.h.

Находим его в скачанном пакете и копируем в папку проекта Drivers\STM32F1xx_HAL_Driver\INC\.

Загрузка файлов в проект

Теперь подключим этот драйвер в заголовочном файле main.h.

/* USER CODE END Includes */

Теперь мы можем в программе вызывать функции, LL GPIO драйвера.

Управление портами ввода-вывода.

Давайте разрабатывать программу.

Разрешим работу портов с помощью HAL-функций, так как мы сделали в предыдущем уроке.

/* USER CODE BEGIN SysInit */

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

Перед использованием библиотеки LL лучше просмотрите ее функции в справочнике.

Оставьте справочник открытым (он открывается в дополнительном окне) и заглядывайте в него в ходе урока.

Вывод PB12 нам надо установить в режим - вход с подтягивающим резистором, подключенным к шине питания.

Используем функцию LL_GPIO_SetPinMode(). Вариант подключения подтягивающего резистора выбираем функцией LL_GPIO_SetPinPull().

/* USER CODE BEGIN SysInit */

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

// конфигурация вывода PB12 на вход
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_12, LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_12, LL_GPIO_PULL_UP);

Не нахожу ничего, что надо пояснять.

Настраиваем вывод PB13 на активный выход.

// конфигурация вывода PB13 на выход
LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_13, LL_GPIO_MODE_OUTPUT);
LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_13, LL_GPIO_OUTPUT_PUSHPULL);

Конфигурация закончена. Получилось проще и понятнее, чем в предыдущем уроке с HAL-драйвером.

Пишем блок реализации алгоритма управления светодиодом. Размещаем его перед тегом:

/* USER CODE END WHILE */

Проверяем состояние кнопки. Для этого считываем состояние порта функцией LL_GPIO_ReadInputPort() и проверяем 12й бит.

if( (LL_GPIO_ReadInputPort(GPIOB) & (1 << 12)) != 0 )
// на выводе PB12 высокий уровень, кнопка отжата
>
else
/ / на выводе PB12 низкий уровень, кнопка нажата
>

Можно использовать функцию не чтения всего порта, а проверки его битов LL_GPIO_IsInputPinSet(). Проверяем вывод LL_GPIO_PIN_12.

if( LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_12) != 0 )
// на выводе PB12 высокий уровень, кнопка отжата
>
else
// на выводе PB12 низкий уровень, кнопка нажата
>

Для управления состоянием светодиода будем использовать функции LL_GPIO_SetOutputPin() и LL_GPIO_ResetOutputPin(). Они устанавливают и сбрасывают заданные выводы.

if( LL_GPIO_IsInputPinSet(GPIOB, LL_GPIO_PIN_12) != 0 )
// на выводе PB12 высокий уровень, кнопка отжата
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_13); // установка
>
else
// на выводе PB12 низкий уровень, кнопка нажата
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_13); // сброс
>

Компилируем, загружаем в плату, проверяем.

Макет устройства

Полностью проект можно загрузить по ссылке:

Зарегистрируйтесь и оплатите. Всего 60 руб. в месяц за доступ ко всем ресурсам сайта!

Думаю, вы согласитесь с моим утверждением в начале урока, что работать с портами ввода-вывода через LL-функции очень просто. Но более сложной периферией мы будем управлять с помощью библиотеки HAL.

В следующем уроке, скорее всего, займемся обработкой дребезга кнопки. Не хочется полностью повторять последовательность тем уроков Ардуино, но не могу представить ни одну программу без кнопки, переключателя, дискретного датчика и т.п.

Читайте также: