скрытое меню

UART первый проект

DTE - Data Terminal Equipment - ПЕРЕДАТЧИК
DСE - Data Circuit-Terminating Equipment - ПРИЕМНИК

фотка 1

115200 макс скорость, пакет макс 9бит (отклонение макс. частоты приемника / передатчика 10%)

Аппаратный контроль CTS / RTS

CTS - (Clear to send) - вход для разрешения Передатчику посылать данные. Передатчик ждет для передачи CTS = 0.
RTS Request to send - запрос COM-порта на передачу данных (сигнал COM-порта о готовности принимать данные).

Data terminal ready - сигнал готовности COM-порта к обмену данными.
Data set ready - вход сигнала готовности от подключённого к порту устройства.

STM32407VE** (тренируемся - все на одной плате)

фотка 2

Желтый и черный это RTS-CTS, CTS-RTS
зеленый и синий Tx-Rx, Rx-Tx

Для простоты - USART3 только передача, USART2 только прием. Гоним байты только в одну сторону. FreeRtos не используем. Все по минимуму.

Вариант 1: Работаем через прерывания HAL

Не скрою убито 2 дня. Поиски в интернете как ни странно не много дают. Но главное это логика и копание в исходниках HAL-а.

У нас с порта UART2 данные сразу шлются на UART3 того же контроллера!

Связка HAL_UART_Transmit_IT (HAL_UART_TxCpltCallback) , HAL_UART_Receive_IT (HAL_UART_RxCpltCallback) :

1. HAL_UART_Receive_IT и HAL_UART_Transmit_IT - это всего лишь команда к активации режима прерываний!

С предачей обычно все проще - мы знаем когда она начинается (мы начинаем передачу).

А вот прием вообще предположительно не понятный : когда , сколько байт придет непонятно (и придет ли вообще).

Поэтому рассмотрим прием отдельно:

HAL_UART_Receive_IT (..,rxBuf,toRead) HAL_UART_RxCpltCallback

По HAL_UART_Receive_IT активируется прием данных в НЕ блокирующем режиме , т.е. программа выполняется далее без блокировки.

Далее все зависит от механизма прерываний.

HAL_UART_RxCpltCallback вызывается из обработчика прерываний и тут мы смотрим сколько мы запросили принять toRead (в HAL_UART_Receive_IT ) и это есть RxXferSize и сколько приняли уже в буфер (rxBuf) это = RxXferSize - RxXferCount. Соответсвенно RxXferCount сколько еще осталось принять.
То есть RxXferCount уменьшается от toRead до 0 по мере поступления байтов.

Важно для понимания , что состояние порта становится сразу HAL_UART_STATE_BUSY_RX после HAL_UART_Receive_IT.

Так вот почему надо прием делать по 1 байту

Если запустить HAL_UART_Receive_IT (..,rxBuf,toRead) с toRead=2 и придет например 5 байт, то получится , что 2 байта HAL_UART_RxCpltCallback примет , а вот 3,4,5 байты где-то потеряются. Так как пока вы будете обрабатывать приход 2 байт , оставшиеся не будут ждать, они будут приходить , но их никто не будет ждать и принимать.

По-этому ВАЖНО в HAL_UART_RxCpltCallback обработчике прерываний сразу запускать прием следующих байт, после получения запрошенных. Но поскольку оперативно мы не можем знать сколько еще должно придти , то проще принимать тупо по 1 байту и сразу запускать прием следующего.

И тут есть важный момент если мы запросим прием 1 байта, нам может прийти на самом деле и 3 байта (RxXferSize =3). Почему ?
Потому , что есть понятие интервала между 2 байтами. Если они идут подряд , значит прием продолжается пока не возникнет пауза между байтами больше какой-то величины.

Соответственно тут надо использовать кольцевой буфер, в который попадает весь прием. И извлекать из этого буфера принятые байты не мешая одновременному дальнейшему приему.

Callback functions

Не забывайте использовать HAL_UART_ErrorCallback и некоторые другие коллбеки , туда залетают полезные по информативности проблемы - переполнение и др.

Открытый проект как всегда прикладываю ниже

Сделан на открытой платформе Atollic TrueStudio

фотка 3

Файлы для скачивания

* STM32F407VET6 UART2 UART3 Atollic [zip]
отркрытый полностью проект