Stm32 что такое hal
Слой аппаратной абстракции HAL
Последняя библиотека — слой аппаратной абстракции (англ. Hardware Abstraction Layer, HAL). Ее основные задачи — сократить время разработки и позволить писать портируемый на любое семейство STM32 (F0, F1 и т.д.) код. С одной стороны, она похожа на стандартную библиотеку: для инициализации периферийного блока используется структура. Перепишем инициализацию порта ввода-вывода с использованием библиотеки HAL:
Все модули подключаются через конфигурационный файл stm32f1xx_hal_conf.h :
Не надо думать, что на этом все особенности библиотеки заканчиваются. Если речь не идет об общих или системных ресурсах (GPIO, SysTick, NVIC, PWR, RCC, FLASH), вводится еще одна сущность — дескриптор (англ. handle). Он используется для полного описания объекта 1 в системе. Если мы говорим о модуле коммуникации (USART, SPI, I 2 C и т.д.), мы должны помнить о его основной задаче — обмене данными, которые обычно хранятся в буфере. Проблема в том, что нужно завести как минимум два массива (на прием и на отправку) плюс еще две переменных (или макроса) с размером буферов. У блока может быть несколько режимов работы (через USART реализуется IrDA и SMARTCARD, например), кроме того, сам блок имеет внутреннее состояние (он сейчас что-то отправляет или, наоборот, ожидает команд). В устройстве при этом может находится несколько таких блоков — два, три, кто знает? В итоге получается, что для обслуживания одного «экземпляра» (англ. instance) USART требуется создать кучу переменных, в именовании которых можно легко запутаться. Логичным решением является обертка всех этих переменных в структуру.
Описание драйверов HAL STM32F4xx, частичный перевод
Делюсь небольшой проделанной работой — это частичный перевод оригинального описания
HAL разработан для применения такой архитектуры программирования, когда необходимые функции выполняются верхним слоем приложения, за счет применения промежуточного уровня HAL. При такой архитектуре программирования верхний уровень приложения не «привязан» к микроконтроллеру (МК), т.к обращается к ресурсам МК только через библиотеку драйверов HAL. Такая структура пользовательского приложения улучшает повторное использование кода, и гарантирует его легкую переносимость на другие устройства STM32.
Драйверы HAL предоставляют полный набор готовых к использованию API, которые упрощают реализацию пользовательского приложения. В качестве примера — встроенные устройства коммуникации (связи) содержат интерфейсы API для инициализации и настройки устройства, управления передачей данных на основе опроса, в прерываниях или через DMA, а так же для управления ошибками связи.
API-интерфейсы драйверов HAL, делятся на две категории: 1) Общие (generic) API, которые обеспечивают общие, для всех серий STM32, функции. 2) Расширенные (extension) API, которые содержат специфические или индивидуальные функции для данного семейства или его части.
Драйверы HAL являются функционально-ориентированными, а не ориентированны на внутренние периферийные устройства. Например, API таймера делится на несколько категорий, по функциям, предоставляемым внутренним устройством таймера: базовый таймер (basic timer), захвата (capture), широтно-импульсной модуляции (PWM), и т.д…
Исходный код библиотеки драйверов разработан в соответствии со Strict ANSI-C, что делает код независимым от инструментов разработки. Весь исходный код проверен с помощью инструмента статистического анализа CodeSonarTM, полностью документирован и является MISRA-C 2004 совместимым.
Драйверы слоя HAL реализуют обнаружение ошибок во время выполнения (run-time failure detection), HAL проверяет входные значения всех функций. Такая динамическая проверка способствует повышению надежности встроенного ПО. Обнаружение ошибок во время выполнения программы, также, способствует ускорению разработки пользовательских приложений и процесса отладки.
Далее — в приложенном файле
Сразу скажу, что переведена, фактически, только 2 глава, в которой описано, как устроен HAL. Старался перевести максимально «корректно», а как получилось…
Если кем-то будут замечены ляпусы — исправлю.
Обсуждение на форуме
HAL stm32
HAL (Hardware Abstraction Layer) — это библиотека для создания приложений на stm32, разработанная компанией ST в 2014 году. HAL пришёл на смену SPL.
Заранее скажу, что эта статья никакой не мануал, это просто попытка описать внутреннее устройство HAL, ну или можно сказать, что это метод изучения сабжа.
Итак, HAL позволяет абстрагироваться от работы с регистрами и прочей сложной магии. Грубо говоря, HAL это обёртка над низкоуровневыми операциями. Конечно же это не отменяет необходимости понимания устройства микроконтроллеров, но значительно снижает уровень вхождения.
Например, чтоб запустить таймер, достаточно перед бесконечным циклом прописать вот такую функцию…
То есть нам не нужно знать какие регистры отвечают за это, и что в них записывать. Более того, эта функция будет работать на любых микроконтроллерах серии stm32.
Сама функция выглядит так:
Вначале происходит проверка параметров на ошибки (assert_param), и после этого активируется прерывание и запускается таймер.
Однако я немного забежал вперёд. Прежде чем изучать HAL, нужно познакомиться с программой CubeMX (в просторечии «Куб») так как HAL является неотъемлемой частью «Куба», и именно в нём генерится весь начальный код будущего приложения включая описанные выше функции. Подробно про CubeMX читайте здесь.
Познакомились — тогда продолжим…
Воспользуемся примером, который сделан по ссылке выше, и рассмотрим подробно всю программу.
Итак мы сгенерировали проект, в котором есть таймер вызывающий прерывание при переполнении, и GPIO. Открываем этот проект в среде разработки (у меня TrueStudio) и в левой панели клацаем файл main.c…
Куб создал все необходимые функции инициализации…
void SystemClock_Config(void) — инициализация тактирования.
static void MX_TIM1_Init(void) — инициализация таймера.
static void MX_GPIO_Init(void) — инициализация GPIO.
… и избавил нас от возни с настройками, и от возможных ошибок.
Все функции типичны — параметры записываются в структуры, и адреса этих структур передаются в соответствующие HAL-функции. Каждая функция возвращает статус. Если возвращается ошибка, то вызывается функция Error_Handler() находящаяся в самом низу. В эту функцию хорошо бы прописать что-то, что сигнализировало бы об ошибке, например мигнуть лампочкой.
В конце файла обрисован механизм передачи assert_param() в void assert_failed()…
Если хотите чтоб он раскомментировался, то надо в Кубе сделать так…
Enable Full Assert. Эти ассерты занимают определённое количество памяти, поэтому их лучше использовать только для отладки, а в релизе отключать.
В общем с проверками на ошибки у HAL’а всё очень удобно и информативно.
Теперь давайте рассмотрим процесс инициализации на примере таймера.
Здесь происходит следующее:
Проверяется не пустой ли указатель структуры (htim == NULL) и заполнены ли все элементы структуры (assert_param).
Проверяется статус таймера (htim->State == HAL_TIM_STATE_RESET). В данном случае статус HAL_TIM_STATE_RESET говорит о том, что устройство еще не инициализировано или отключено.
Если статус удовлетворяет, то снимается блокировка (htim->Lock = HAL_UNLOCKED) и вызывается функция HAL_TIM_Base_MspInit(htim) …
Здесь проверяется какой именно таймер настраивается (htim_base->Instance==TIM1) и вызываются функции которые включают тактирование таймера, активирует прерывание и настраивают приоритет.
Далее устанавливается статус «занято» (htim->State= HAL_TIM_STATE_BUSY) — если по каким-то причинам, параллельно будет вызвана ещё одна функция инициализации таймера, то она не сможет ничего испортить.
После этого вызывается функция TIM_Base_SetConfig(htim->Instance, &htim->Init) (у этой функции нет приставки HAL, поэтому можно назвать её низкоуровневой) работающая напрямую с регистрами…
Ну и наконец устанавливается статус «готов к труду и обороне» (htim->State= HAL_TIM_STATE_READY) и возвращается — return HAL_OK;
Все функции имеют характерные названия определяющие их назначение…
Окончание _IT означает, что устройство будет вызывать прерывание. Это относится к любым функциям используемым в HAL.
Например запуск таймера без прерываний выглядит так:
Как вы уже наверно поняли, одна из особенностей библиотеки HAL это большое количество проверок защищающих разработчиков от массы неприятностей. Кто-то расценит это как добродетель, а кто-то решит что такое количество проверок избыточно. Однако не стоит занимать какую-либо позицию на этот счёт так как в процессе изучения вы поймёте где нужно оставлять эти проверки, а где их можно удалить. То же самое касается и всего остального, со временем вы будете отказываться от каких-то функций HAL и заменять их работой с регистрами.
При работе с любой другой периферией, все необходимые функции вы найдёте в соответствующих файлах…
Названия файлов говорят сами за себя.
Функция запуска таймера…
… сама по себе не особо интересна.
Функция устанавливает бит разрешающий прерывания по переполнению — __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE) и бит активации таймера — __HAL_TIM_ENABLE(htim).
А вот механизм вызова прерывания поможет понять устройство библиотеки HAL. Разберём его…
Когда мы в Кубе активируем прерывание от какой-либо периферии, то в файле stm32f1xx_it.c автоматически создаётся обработчик с соответствующим именем…
Сюда программа переходит как только сработает прерывание от любого из событий таймера №1.
Программа войдя в функцию HAL_TIM_IRQHandler проверяет какой из флагов был установлен и найдя нужный блок выполняет его содержимое.
Нас интересует блок TIM Update event…
Библиотека HAL под завязку напичкана различными макросами. Как уже говорилось в начале статьи, они начинаются с __двойного подчёркивания и имеют характерные имена определяющие их назначение. Эти макросы очёнь клёвая штука, они позволяют оперировать различными битами в различных регистрах без необходимости копаться в даташитах.
Внутри макроса __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE) содержится вот такая конструкция…
Этот макрос сбрасывает бит (указанный вторым аргументом) в регистре состояния (Status Register).
В первый аргумент подставляется указатель на структуру таймера, а вторым аргументом идёт дефаин флага который взводится при возникновении прерывания…
Написав программу на HAL вы можете проследить где-какие макросы/функции вызываются, и работать с регистрами напрямую. То есть HAL можно с лёгкостью использовать как пособие для изучения низкоуровневых операций.
Колбек это характерная фишка HAL’а. В колбеках выполняются действия которые нужно сделать при возникновении события/прерывания, в нашем случае мы будем мигать лампочкой.
В принципе нам ничто не мешает мигать лампочкой прямо в обработчике, да ещё и оперировать регистрами напрямую (немного хардкора)…
В этом примере делается то же самое, что делает HAL — сбрасывается флаг прерывания и вместо вызова колбека сразу же выполняется действие (мигание светиком).
Таким образом количество кода сократилось бы в разы, но не было бы никаких проверок, и в любом случае нужно было бы самостоятельно писать проверку — какое именно событие случилось (если бы их было несколько). Тем не менее, в дальнейшем, когда хорошенько прокачаетесь, будете потихонечку переходить на работу с регистрами.
Если вы внимательно посмотрите, то увидите что у каждого события есть свой колбек. Например у захвата/сравнения их несколько…
Находим нужный нам колбек…
… и переопределяем его в файл main.c
Проверяем что прерывание пришло от таймера №1 и мигаем светиком.
Проверять от какого таймера пришло прерывание нужно в том случае, если используется несколько таймеров. Тут дело вот в чём: если мы настроим ещё один таймер, например №2, и он тоже будет вызывать прерывания, тогда в файле stm32f1xx_it.c появится второй обработчик…
Не смотря на то, что обработчиков два, функция HAL_TIM_IRQHandler() одна и та же. Соответственно и колбек будет вызываться один и тот же. Поэтому для двух таймеров нужно делать так…
Это касается не только таймеров, но и прочей периферии — USART, SPI, I2C и т.д.
Рассмотрим работу USART’а с DMA, там механизм несколько сложнее чем с таймером. В Кубе настройте USART с использованием DMA на приём…
Инициализация USART’а точно такая же как и у таймера…
Параметры загружаются в структуру и передаются в функцию.
Команда запуска опять же схожа с таймером (передаётся структура + доп. аргументы)…
Первый аргумент это адрес структуры, второй — это адрес массива в который будут складываться полученные данные, третий — это количество байт которые нужно принять.
Здесь у нас много чего интересненького.
В первую очередь происходит проверка — занят USART или нет (HAL_UART_STATE_READY).
Если до этого функция уже запускалась и данные ещё не получены, то эта проверка не пройдёт и функция вернёт статус «занято» (return HAL_BUSY). Если же необходимо перезапустить функцию, то предварительно надо вызвать — HAL_UART_AbortReceive(&huart1). Как видите названия функций говорят сами за себя.
Следом идёт запуск DMA — HAL_DMA_Start_IT() …
В функцию передаётся: указатель на структуру, источник данных (в нашем случае это регистр данных (DR) USART’а), получатель данных (адрес буфера), и ожидаемое кол-во байт.
Если элемент структуры hdma->XferHalfCpltCallback не пустой, то разрешаются прерывания по заполнению буфера полностью (DMA_IT_TC), по заполнению буфера наполовину (DMA_IT_HT), и при ошибке (DMA_IT_TE). Если нам не нужно отслеживать заполнение половины буфера, то надо в huart->hdmarx->XferHalfCpltCallback записать NULL.
На этом функция HAL_UART_Receive_DMA(&huart1, (uint8_t*)rx_buff, BUFSIZE) закончена.
Низкоуровневый обработчик прерываний от DMA выглядит так же как и в случае с таймером…
… вызывает HAL-обработчик HAL_DMA_IRQHandler(&hdma_usart1_rx);
И опять же как и у таймера, функция состоит из нескольких блоков. Первый блок срабатывает при заполнении половинки буфера, второй — целиком, а третий при ошибке. Для примера рассмотрим блок полного буфера…
Проверяются флаги полного буфера (DMA_FLAG_TC1) и разрешённого прерывания (DMA_IT_TC).
Блокировка организована очень просто…
Такая вот хитроумная конструкция
Если приём ведётся без DMA…
Тогда после включения глобального прерывания USART’а появится его обработчик…
Следом проверяется счётчик принятых байт — RxXferCount (он считает «вниз» от максимального значения буфера), и если он равен нулю (то есть приняты все запрошенные данные), то вызывается колбек — HAL_UART_RxCpltCallback(huart);
В завершение хочется рассказать про копирование через DMA. Для этого режима у DMA есть механизм создания колбеков.
Настроим Куб для копирование массива из одной области памяти в другую при помощи DMA…
Длина слова указана Word (32 бита), то есть копироваться будет по четыре байта за один такт.
Функция регистрации колбека…
В функцию передаются три аргумента:
1. Указатель на структуру.
2. Ключ, по которому определяется какое событие должно вызвать колбек — скопирован весь буфер, скопирована половина буфера и т.д.
В нашем случае указан полный буфер — HAL_DMA_XFER_CPLT_CB_ID.
3. Название колбека. Придумайте сами.
Функция запуска копирования…
Аргументы: указатель на структуру, массив из которого копируется, массив в который копируется, количество байт (ячейки массива 8-ми битные, а DMA будет копировать по 32 бита за раз).
Содержимое этой функции поизучайте самостоятельно, вы уже всё знаете
По окончанию копирования произойдёт прерывание и будет вызван обработчик…
В функции HAL_DMA_IRQHandler() прописан такой же механизм как и в случае с USART’ом — несколько блоков отвечающих за каждое событие (полный буфер, половинка и т.д.) и вот это…
Элемент структуры hdma->XferCpltCallback был заполнен во время регистрации колбека.
На этом наверно всё.
Всем спасибо
Русские Блоги
HAL библиотека для STM32
1 Три метода разработки STM32
Обычно, когда новички начинают работать с STM32, они должны сначала выбрать метод разработки, который будет использоваться.Разные методы разработки приведут к тому, что ваша архитектура программирования будет совершенно другой. Как правило, большинство людей выбирают стандартную библиотеку и библиотеку HAL, и очень немногие люди разрабатывают путем непосредственной настройки регистров. Описание стандартной библиотеки и библиотеки HAL в Интернете, как полагают, бесчисленное множество. Но для многих новых друзей я до сих пор не понимаю разницу между этими разными методами разработки, поэтому я хочу выразить эти вещи с моим собственным пониманием в очень простой форме. Если в описании что-то не так или есть другие мнения, вы также можете высказать это.
Во-первых, напрямую настроить регистр
Многие друзья, которые сначала узнали 51, могут знать, что будет небольшое количество людей или учебных пособий, которые реализуют функции путем непосредственного управления регистрами на ассемблере. Этот метод не будет работать в STM32. Слишком прост в работе, потому что количество регистров STM32 в десять раз больше, чем у однокристального микрокомпьютера 51, поэтому многие регистры не могут быть полностью запомнены. Во время разработки часто необходимо проверить таблицу данных микросхемы. В настоящее время непосредственное управление регистрами становится очень трудоемкая. Тем не менее, все еще будет небольшое количество людей, которые хотели бы напрямую управлять регистрами, потому что это ближе к принципу, и они знают, почему.
2 Установка библиотеки прошивок библиотеки HAL и руководство пользователя
1. Сначала настройте куб для автоматической загрузки соответствующей библиотеки микропрограмм из сети.
выберите настройки средства обновления
Установить как показано ниже
2. Выберите нужную прошивку в соответствии с чипом
Версия обратно совместима, и вы можете напрямую выбрать последнюю версию. Но если вы считаете, что последняя версия слишком велика, вы можете прочитать основные изменения ниже: она может поддерживать ваш текущий чип.
После выбора нажмите «Установить сейчас». Процесс может быть немного длинным. Рекомендуется загрузить непосредственно на местный официальный сайт, а затем установить
Реализация соответствующих функций под каждую модель
Руководство пользователя находится в папке Drivers.
Автор: My Мужи Мин
Источник: CSDN
Оригинал:https://blog.csdn.net/sinat_37853238/article/details/85141168
Заявление об авторском праве: эта статья является оригинальной статьей блоггера, перепечатайте ссылку на пост в блоге!
3 Разница между библиотекой STM32 HAL и стандартной библиотекой _ Поговорим о дескрипторе, функции MSP, функции обратного вызова
3.1 Ручка
Дескриптор (handle) имеет множество значений, первое из которых относится к программированию, второе относится к программированию Windows. Сейчас большинство из них относятся к программированию / разработке программ。
Предположим, что в стандартной библиотеке STM32 мы хотим инициализировать периферийное устройство (здесь в качестве примера взят USART), нам сначала нужно инициализировать их различные регистры. В стандартной библиотеке эти операции реализуются с помощью переменной структуры библиотеки встроенного программного обеспечения + функция инициализации библиотеки встроенного программного обеспечения:
Как видите, для инициализации последовательного порта вам необходимо:
В библиотеке HAL переменные структуры инициализации USART также определены как глобальные переменные. 。
Щелкните правой кнопкой мыши, чтобы просмотреть элементы структуры
Мы обнаружили, что, в отличие от стандартной библиотеки, этот член не только:
Например, функции обратного вызова MSP и Callback будут описаны позже:
В этих функциях необходимо только вызвать дескриптор UART1_Handler, определенный во время инициализации.
3.2.MSP функция
MSP: специальный пакет MCU
MSP относится к инициализации, связанной с MCUЦитируя объяснение пунктуальных атомов, я лично считаю, что это очень ясно:
Мы хотим инициализировать последовательный порт, мы должны сначала установить вещи, которые не имеют ничего общего с MCU, такие как скорость передачи, четность, остановка
биты и т. д. Эти настройки параметров не имеют ничего общего с MCU, вы можете использовать STM32F1 или STM32F2 / F3 / F4 / F7
. Для последовательного устройства требуется MCU для его переноса, например, STM32F4 используется в качестве канала-носителя, а PA9 используется в качестве отправителя.
для отправки, PA10 в качестве получателя, MSP инициализирует PA9, PA10 в STM32F4 и конфигурирует эти два контакта. Так ХАЛ
Процесс инициализации драйвера :
В драйвере HAL STM32 HAL_PPP_MspInit () используется в качестве обратного вызова, который вызывается функцией HAL_PPP_Init (). Когда нам нужно перенести программу на платформу STM32F1, нам нужно только изменить содержимое функции HAL_PPP_MspInit без изменения содержимого параметров записи HAL_PPP_Init.
В библиотеке HAL почти каждому периферийному устройству необходимо установить соединение между периферийным устройством и микроконтроллером, таким как порт ввода-вывода, мультиплексирован ли он и т. Д. Можно видеть, что библиотека HAL имеет больше функций MSP, чем стандартная библиотека, и она переносима Очень сильный, но в то же время это увеличивает объем кода и уровень вложенности кода. Есть плюсы и минусы.
Точно так же функции MSP могут взаимодействовать с дескрипторами для достижения очень сильной переносимости:
Параметру ввода нужен только дескриптор последовательного порта, поэтому его удобно видеть.
3.3.Callback функция
Подобно функции MSP, я лично считаю, что функция обратного вызова в основном помогает пользователям писать код на прикладном уровне.
Возьмем в качестве примера USART. В стандартной библиотеке после прерывания последовательного порта мы должны сначала определить, следует ли получать прерывание в прерывании, затем прочитать данные, кстати снять флажок прерывания, а затем обработать данные, поэтому, если мы Написание такого большого количества кода в функции прерывания может сбить с толку:
В библиотеке HAL после ввода прерывания последовательного порта она непосредственно размещается функцией прерывания библиотеки HAL:
HAL_UART_IRQHandler Эта функция завершает определение того, какое прерывание (получить? Отправить? Или другое?), А затем считывает данные, сохраняет их в буферной области, очищает флаг прерывания и так далее.
Например, если я установлю его заранее, каждые пять байтов, полученных последовательным портом, я обработаю эти пять байтов.
В начале я определил буфер приема последовательного порта:
В инициализации я установил адрес области буфера и размер буфера (пять байтов) в дескрипторе.
В полученных данных HAL_UART_IRQHandler будет выполнять функцию обратного вызова каждые пять байтов после получения:
В этой функции обратного вызова нам требуется обработать только пять полученных байтов (сохраненных в aRxBuffer []), и нет необходимости вручную очищать флаги и другие операции.
Так сказатьФункция обратного вызова является функцией кода прикладного уровня. Сначала мы устанавливаем параметры в дескрипторе, а затем ждем, пока библиотека HAL отправит код, который мы подготовили, в наши руки.
4 Структура библиотеки STM32 HAL
Когда дело доходит до библиотеки STM32 HAL, я должен упомянуть STM32CubeMX, как инструмент визуальной конфигурации для разработчиков, это действительно экономит время разработки. STM32CubeMX основан на библиотеке HAL и в настоящее время поддерживает только библиотеки HAL и LL! Сначала рассмотрим структуру include официальной библиотеки HAL:
Сразу же он будет содержать stm32f4xx_hal.h.
Далее описываются исходные файлы библиотеки HAL. Имена файлов библиотеки HAL начинаются с stm32f4xx_hal, за которым следует _ имя периферийного устройства или модуля (например, stm32f4xx_hal_adc.c):
В соответствии с правилами именования библиотеки HAL ее API можно разделить на следующие три категории:
Примечание:
В настоящее время библиотека LL связана с библиотекой HAL, поэтому в исходном коде библиотеки HAL есть некоторые исходные файлы с именем stm32f2xx_ll_ppp. Эти файлы являются недавно добавленными файлами библиотеки LL.
При использовании производственного проекта CubeMX вы можете выбрать библиотеку LL
Соответствующие знания заключаются в следующем:
Как видно из приведенного выше определения, ADC_HandleTypeDef содержит все определения, которые могут встречаться в ADC. Для пользователей, которые хотят использовать ADC, просто определите переменную ADC_HandleTypeDef, присвойте значение каждой переменной, и соответствующее периферийное устройство будет абстрагировано. Следующим шагом является его использование.
Конечно, Для этих общих периферийных устройств или системных периферийных устройств им не нужно создавать такие абстракции. ,Эти части в основном совпадают с оригинальными стандартными функциями периферийной библиотеки., Например, следующие периферийные устройства:
— GPIO
— SYSTICK
— NVIC
— RCC
— FLASH
В качестве примера рассмотрим GPIO. Для функции HAL_GPIO_Init () требуется только адрес GPIO и параметры инициализации.
(2) Три метода программирования
Библиотека HAL также объединяет все функциональные модели. В библиотеке HAL поддерживаются три режима программирования:Режим опроса, режим прерывания, режим DMA(Если поддерживается периферийным устройством). Они соответствуют следующим трем типам функций (на примере АЦП):
Среди нихС _IT означает работу в режиме прерывания, работа с _DMA в режиме DMA(Примечание: прерывания также включены в режиме DMA);Ничего не принесло это режим опроса(Без включенных прерываний). От того, какой метод использует пользователь, зависит от его выбора.
Также В новой архитектуре библиотеки HAL макросы используются для настройки различных прерываний и т. Д. (Исходные стандартные периферийные библиотеки, как правило, представляют собой все виды функций). Следующие макросы в основном используются для каждого типа периферийных устройств:
__HAL_PPP_ENABLE_IT(HANDLE, INTERRUPT): Включить указанное периферийное прерывание
__HAL_PPP_DISABLE_IT(HANDLE, INTERRUPT):Отключить указанное периферийное прерывание
__HAL_PPP_GET_IT (HANDLE, __ INTERRUPT __):Получить указанный статус периферийного прерывания
__HAL_PPP_CLEAR_IT (HANDLE, __ INTERRUPT __):Очистить состояние прерывания указанного периферийного устройства
__HAL_PPP_GET_FLAG (HANDLE, FLAG):Получить статус флага указанного периферийного устройства
__HAL_PPP_CLEAR_FLAG (HANDLE, FLAG):Очистить состояние флага указанного периферийного устройства
__HAL_PPP_ENABLE(HANDLE) :Включить периферию
__HAL_PPP_DISABLE(HANDLE) :Отключенная периферия
__HAL_PPP_XXXX (HANDLE, PARAM) :Макро определения для указанных периферийных устройств
_HAL_PPP_GET IT_SOURCE (HANDLE, __ INTERRUPT __):Проверьте источник прерывания
(3) Три основные функции обратного вызова
В исходном коде библиотеки HAL есть некоторые функции, начинающиеся с __weak, и некоторые из этих функций были реализованы, например:
Некоторые не реализованы, например:
1. Функция обратного вызова инициализации / деинициализации на уровне периферийной системы(Вторая часть кода пользователя: обработка MSP): HAL_PPP_MspInit () и HAL_PPP_MspDeInit ** Например: __weak void HAL_SPI_MspInit (SPI_HandleTypeDef * hspi). Вызывается в функции HAL_PPP_Init () для инициализации базовых связанных устройств (GPIO, часы, DMA, прерывание)
Большая часть кода пользователя реализована в трех вышеупомянутых функциях обратного вызова.
В структуре библиотеки HAL необходимо вызывать соответствующую функцию DeInit перед каждой инициализацией (особенно перед ее многократным вызовом). 。
Ошибка вызова return, когда некоторые периферийные устройства инициализируются несколько раз, приведет к сбою инициализации. Существует много функций обратного вызова завершения, например, функции обратного вызова завершения для последовательного порта включают HAL_UART_TxCpltCallback и HAL_UART_TxHalfCpltCallback.
(третья основная часть пользовательского кода: обработка различных функций обратного вызова во втором и третьем пунктах выше)
При фактическом использовании я обнаружил, что с HAL все еще много проблем, таких как проблема конфигурации библиотеки при использовании USB
5 HAL портирование библиотеки
Основные шаги
1. Скопируйте stm32f2xx_hal_msp_template.c, обратитесь к этому шаблону и реализуйте HAL_PPP_MspInit () и HAL_PPP_MspDeInit периферийных устройств, используемых по очереди.
2. Скопируйте stm32f2xx_hal_conf_template.h. Пользователи могут свободно обрезать этот файл и настраивать библиотеку HAL.
3. При использовании библиотеки HAL сначала необходимо вызвать функцию: HAL_StatusTypeDef HAL_Init (void) (эта функция определена в stm32f2xx_hal.c, что означает, что в первом пункте вы должны сначала реализовать HAL_MspInit (void) и HAL_MspDeInit (void))
4. Библиотека HAL отличается от библиотеки STD. Библиотека HAL использует функции в RCC для настройки системных часов. Пользователь должен написать функцию конфигурации часов отдельно (по умолчанию для библиотеки STD используется system_stm32f2xx.c)
5. Что касается прерываний, HAL предоставляет функции обработки прерываний. Вам нужно только вызвать функции обработки прерываний, предоставляемые HAL. Собственный код пользователя не рекомендуется сначала записывать в прерывание, но его следует записывать в функцию обратного вызова, предоставляемую HAL.
6. Для каждого периферийного устройства HAL предоставляет функцию обратного вызова, которая используется для реализации собственного кода пользователя. Вся структура вызовов выполняется самой библиотекой HAL. Например: В Uart HAL предоставляет функцию void HAL_UART_IRQHandler (UART_HandleTypeDef * huart);; После того, как пользователю нужно только вызвать прерывание, ему нужно только вызвать функцию. В то же время напишите свой собственный код в соответствующей функции обратного вызова! Следующим образом:
Используйте любую функцию обратного вызова, которую вы используете!
Базовая структура
Итак, основная структура (на примере последовательного порта) написания программы (для определенного периферийного устройства) с использованием библиотеки HAL выглядит следующим образом: