STM32 HAL Uart

В сегодняшней статье рассмотрим как работать с функциями STM32 HAL Uart. подробно разберем каждую функцию, а так же рассмотрим небольшой пример.

STM32 Uart

В микроконтроллерах STM32, в зависимости от количества выводов, может быть от 1 до 6 блоков UART/USART а также LPUART

STM32 Uart в CubeMx
  • UART — Universal asynchronous receiver/transmitter или если по простому асинхронный приема передатчик.
  • USART — Universal Synchronous/Asynchronous Receiver/Transmitter или, синхронный/асинхронный приема передатчик.
  • LPUART — это тот же UART, только с пониженным энергопотреблением.

Прием и передача по Uart может осуществляться в следующих режимах:

  • Прием и передача данных в режиме опроса.
  • Прием и передача данных с помощью прерываний.
  • Прием и передача данных с помощью DMA.

Для каждого из режимов у STM32 имеются свои функции HAL Uart.

Функции HAL UART в режиме опроса

HAL Uart Transmit

Передача данных в режиме опроса осуществляется с помощью функции HAL_UART_Transmit:

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout), где

  • huart — указатель на используемый UART.
  • pData — массив с данным для отправки.
  • Size — количество байт. которые нужно отправить.
  • Timeout — время ожидания отправки.

HAL Uart Receive

Для того, что бы принять данные по UART, необходимо использовать функцию HAL_UART_Receive:

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout), где

  • huart — указатель на используемый UART.
  • pData — указатель на приемный буфер.
  • Size — количество байт, которые нужно принять.
  • Timeout — время ожидания отправки.

ВНИМАНИЕ! В данном режиме функции приема и передачи данных, блокируют работу основного цикла на время приема или отправки данных. Или на время Timeout.

Функции HAL UART в режиме прерываний

HAL Uart Transmit IT

Передача данных в режиме прерываний осуществляется с помощью функции HAL_UART_Transmit_IT:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size), где

  • huart — указатель на используемый UART.
  • pData — массив с данным для отправки.
  • Size — количество байт. которые нужно отправить.

HAL Uart Receive IT

Для того, что бы принять данные по UART в режиме прерываний, необходимо использовать функцию HAL_UART_Receive_IT:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size), где

  • huart — указатель на используемый UART.
  • pData — указатель на приемный буфер.
  • Size — количество байт, которые нужно принять.

В режиме прерываний функции приема и передачи данных не блокируют основной цикл программы, что является плюсом.

Функции HAL в режиме DMA

HAL Uart Transmit DMA

Передача данных в режиме прерываний осуществляется с помощью функции HAL_UART_Transmit_DMA:

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size), где

  • huart — указатель на используемый UART.
  • pData — массив с данным для отправки.
  • Size — количество байт. которые нужно отправить.

HAL Uart Receive DMA

Для того, что бы принять данные по UART в режиме прерываний, необходимо использовать функцию HAL_UART_Receive_DMA:

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size), где

  • huart — указатель на используемый UART.
  • pData — указатель на приемный буфер.
  • Size — количество байт, которые нужно принять.

В режиме DMA функции приема и передачи данных не блокируют основной цикл программы, а так же прием или передача данных осуществляется без участия процессора.

Пример программы на STM32

Рассмотрим пример программы приема передаче через UART c использованием прерываний:

// Использовать будем USART2
uint32_t SIZE_BUFFER = 125;
uint8_t BuferRxDEBUG[SIM8xx_SIZE_BUFFER];

//В main после инициализации UART
MX_USART2_UART_Init();
//необходимо вызвать функцию приема байта. Этим мы активируем начало работы приема
HAL_UART_Receive_IT(&huart2, &getbyteDb, 1);
// Для приема данных будем использовать функцию Callback. Данная функция выполняется когда завершен прием 1 байта.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* Prevent unused argument(s) compilation warning */
    if(huart==&huart2)
    {
	HAL_UART_Receive_IT(&huart2, &getbyteDb, 1);
	BuferRxDEBUG[pGetByteDb] = getbyteDb;
	pGetByteDb++;
        // если достигли признака конца строки, очищаем буфер и обнуляем счетчик принятых байт
	if (RxBuf_Bytes((uint8_t*)BuferRxDEBUG, (uint8_t *) END_OF_MESSAGE_STRING, SIZE_BUFFER))
	{
	     Flush_Buf(BuferRxDEBUG, SIZE_BUFFER);
	     pGetByteDb = 0;
	}
     }
}
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
23 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Владимир
Владимир
13 дней назад

Добрый день, вопрос к вам по поводу функции HAL_UART_Receive(*huart, *pData, Size, Timeout). Столкнулся с тем что параметр Timeout никак не влияет на работу функции. Функция будет выполняться до тех пор пока не примет пакет размера Size, а если пакет не придет или потеряется хотя бы байт, то функция не закончит свою работу даже по прошествию времени Timeout. Т.е. если мы не приняли пакет размера Size, то просто повиснем. Величина В чем может быть причина?

Последний раз редактировалось 13 дней назад Владимир ем
Владимир
Владимир
Ответить на  ginseng
12 дней назад

void Config(void)
{
 unsigned char _packetReceive[37];
extern unsigned char Packet200[45];
USART1_Init();
HAL_UART_Transmit(&huart1, Packet200, 45, 20);
 HAL_UART_Receive(&huart1, _ packetReceive, 37, 40);
 }
Отсылаю пакет (пакет задан вне функции) внешнему устройству через UART и жду от него ответа. Пакет передается за 4мс, ещё через 3 мс получаю ответ в течении 3мс. Этот кусок кода работает хорошо пока приходит ответ, если его не будет (например обрыв линии), то программа виснет наглухо в функции UART_WaitOnFlagUntilTimeout

Последний раз редактировалось 12 дней назад Владимир ем
Юрий
Юрий
2 дней назад

Компилятор ругается на UART_HandleTypeDef в функции void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart). Где чего надо объявить или ещё чего сделать.

Юрий
Юрий
Ответить на  ginseng
2 дней назад

Спасибо за оперативный ответ. Как будет выглядеть этот дискриптор в программе и почему в Вашем примере он не требуется. Дело в том, что как-то всё работало и не возникало вопросов по дескрипторам, т.е я до этого момента и не знаю что это такое и вдруг начал ругаться.

Юрий
Юрий
Ответить на  Юрий
2 дней назад

Да, работа ведётся по USB

Юрий
Юрий
Ответить на  ginseng
1 день назад
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART1)        // USART1 завершил прием данных
   {}
}
Код упростил, это не суть. Пользуюсь STM32CubeIDE 1.12.0, всё генерирую через него. Меня смущает то, что эта проблема возникла вдруг, то есть до этого было нормально. Очень жалко, что я не смог вовремя обратить на это внимание, а так бы связал бы с производимыми мной действиями. Единственное предположение, что ранее работал одновременно и с USART и с USB, а сейчас только с USB. Но это же не при чём.

Юрий
Юрий
Ответить на  Юрий
1 день назад

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

Юрий
Юрий
Ответить на  ginseng
1 день назад

Спасибо за участие. Компилятору не нравится строчка void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart), а именно UART_HandleTypeDef. Повторюсь, что ранее с этой строчкой проблем не было.

Юрий
Юрий
Ответить на  Юрий
1 день назад

Да, а с & спасибо, прозевал.

Юрий
Юрий
Ответить на  ginseng
14 часов назад

Да, именно это. Насквозь всё видите.

Юрий
Юрий
Ответить на  ginseng
9 часов назад

Спасибо. Как уже писал использую только USB в режиме виртуального компорта. Как понимаю, для использования обсуждаемого колбека мне надо подключить UART1. А если он не нужен (только ножки занимает), то что тогда делать?

Юрий
Юрий
Ответить на  ginseng
6 часов назад

Нет, никаких переходников не использую. У STM32 есть возможность сразу на своих ножках организовать USB_DP и USB_DM. В Кубе также есть соответствующие для этого настройки в том числе будет ли он являться виртуальным COM портом или каким иным классом. В случае виртуального COM порта, как понимаю, в нём есть примочка для связи USB и USART. В этом случае обсуждаемый колбек должен работать, но что-то не получается без подключения USART. И как в этом случае его настраивать. Или всёже есть отдельный колбек для USB. Эти мои рассуждения надо рассматривать как дилетантские.