STM32. Передача данных через UART (работа с COM-портом)
В этой статье речь пойдет о простейших способах передачи данных в различном виде UART микроконтроллера. Это крайне полезная функция, которая помогает быстро вывести отладочную информацию или наладить общение с ПК.
Подготовка к работе
Перед началом работы рекомендуем ознакомиться с предыдущими остальными статьями нашего курса. Здесь мы не будем останавливаться на простейших действиях. Напомним только что работа будет производиться с использованием утилиты CubeMX, HAL-драйвера, IDE Keil uVision и платы Nucleo-F030R8.
Обратите внимание, что программатор ST-Link, который входит в состав платы Nucleo, уже имеет на борту преобразователь USB-to-COM. Который в свою очередь уже подключен к основному контроллеру. Это значит, что нам не потребуется абсолютно ничего, кроме самой платы Nucleo-F030R8.
Если вы используете какое-либо альтернативное аппаратное обеспечение, то необходимо найти преобразователь интерфейсов и подключить его к ПК и микроконтроллеру.
Настройка CubeMX
Чтобы включить UART, в самом простом случае, достаточно двух действий.
Во-первых, на вкладке Pinout, надо включить модуль USART2 в асинхронном режиме, как это показано на картинке ниже:
Во-вторых, на вкладке Configuration можно изменить настройки подключения. Мы изменили скорость обмена:
Все. На этом настройка порта завершена. Можно сгенерировать проект и приступить к написанию кода.
Передача строки в ASCII
Самая простая функция для передачи дачи в асинхронном режиме — HAL_UART_Transmit(). Найти ее можно в файле драйвера stm32f0xx_hal_uart.c.
Чуть позже мы разберем аргументы этой функции, а пока сконцентрируемся на результате. Итак, вызовем эту функцию в бесконечном цикле с задержкой и передадим в нее следующие параметры:
Для приема сообщения на стороне компьютера можно использовать любую терминальную программу. Мы будем использовать программу Terminal 1.9b.
Если все сделано верно, то после компиляции и прошивки контроллера, раз в секунду в COM-порт будет отправляться сообщение "Hello world!" с переводом строки. Обратите внимание на настройки терминальной программы — символы печатаются в ASCII-кодировке с переводом строки.
Всего в функцию HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) требуется передать четыре аргумента:
- *huart — указатель на структуру данных, описывающую UART. Ранее мы не сталкивались с указателями и структурами данных. По сути, это набор переменных, объединенных для удобства под общим именем. Объявление этой переменной содержится в начале файла main.c, а описание этой структуры можно найти в файле stm32f0xx_hal_uart.h.
Обратите внимание, что заполнение полей данных этой структуры происходит при инициализации UART в файле main.c.
Унарный оператор * (в аргументе функции *huart) показывает то, что это указатель. То есть в эту функцию необходимо передать не саму структуру данных, а ее адрес в памяти. Получить адрес структуры данных (или обычной переменной) можно при помощи унарного оператора &.
Таким образом, при вызове функции HAL_UART_Transmit(), в качестве первого параметра следует указать &huart2. - *pData — аргумент-указатель на данные, которые необходимо передать. Словами "Hello world!\n" мы создаем массив из элементов типа char. А массив и указатели в Си это, фактически, одно и то же. То есть передавая его в функцию, не надо писать оператор &. Запись (uint8_t*) необходима для преобразования типа данных. Без нее тоже будет работать (так как char и uint8_t это одно и то же), но вы увидите предупреждение.
- Size — количество передаваемых байт. В нашем примере передается 13 символов. В том числе символ перевода строки "\n".
- Timeout — максимальное время работы функции. Скорее всего функции сможет выполнить передачу гораздо быстрее, но, если что-то пойдет не так, через одну секунду она прекратит попытки.
Таким образом у нас получилась запись HAL_UART_Transmit(&huart2, (uint8_t*)"Hello world!", 13, 1000);.
Дополнительные примеры
В реальных системах очень часто возникает обмена данными между различными устройствами. Рассмотренная функция подходит для того, чтобы просто передавать любые данные в виде массива или единичной переменной.
Для примера создадим переменную count. В цикле, раз в секунду, мы будем ее увеличивать и отправлять текущее значение в UART.
В функцию мы передаем указатель на переменную, то есть &count. И указываем, что требуется передать один байт. В терминале, если включить отображение данных в шестнадцатеричном формате, то в выводе мы увидим следующее:
Также иногда требуется передать значение переменной в формате ASCII. Наиболее простой способ, на наш взгляд, показан ниже:
Обратите внимание на использование функции sprintf(). Эта функция позволяет отпечатать в массив элементы с форматным выводом аргументов функции и возвращает количество отпечатанных символов. Тонкости форматного вывода, в качестве справочной информации, описаны в книге Б. Кернигана и Д. Ричи "Язык программирования Си".
Другими словами, одним действием мы передали в функцию массив, заполнили его данными и определили количество элементов. В терминальной программе при этом мы увидим как раз в секунду увеличиваются значения в формате ASCII.
Есть также дополнительные режимы отправки данных через UART с использованием прерываний и технологии прямого доступа к памяти, но на данном этапе мы не будем рассматривать эти варианты. В следующей статье вы речь пойдет о приеме данных.
Ссылки на остальные статьи цикла можно найти здесь.
Мы будем очень рады, если вы поддержите наш ресурс и посетите магазин наших товаров shop.customelectronics.ru.
Метки: COM-порт, HAL, STM32, transmit, UART, передача Просмотров: 51656