Полноценный трехпортовый USB-Serial адаптер на STM32 Blue Pill (STM32F103C8T6)


|

Некоторое время назад мне в очередной раз потребовался USB-Serial адаптер. И не просто адаптер c RX/TX, а чтобы еще присутствовали управляющие сигналы. И не один UART, а несколько. И еще желательно, в виде одного композитного устройства, чтобы все это хозяйство не занимало больше одного USB-порта. Так и началась эта история...

 

Готовые устройства из тех, что можно приобрести в магазине, меня не вдохновили. Либо дорого и сложно найти в продаже, либо не подходят по одному или нескольким критериям выше. Композитных USB-Serial адаптеров в дешевом сегменте я и вовсе не смог найти. Зато на столе обнаружилась отладочная плата STM32 Blue Pill на микроконтроллере STM32F103C8T6. Сверившись с документацией, я убедился, что этот микроконтроллер содержит в себе все, что мне нужно для полного счастья. А именно: интерфейс USB 2.0 full-speed, три USART, семиканальный DMA контроллер и достаточное количество линий GPIO для реализации всех интересующих меня управляющих сигналов.

 

Осталось только раздобыть соответствующую прошивку, которая превратит безжизненный кусок железа в нужное и полезное устройство. И тут меня поджидало большое разочарование: оказывается, несмотря на бешеную популярность этого микроконтроллера и отладочной платы, никто до сих пор так и не сделал ничего подобного. Вернее, попытка была, но это скорее экспериментально-образовательный proof-of-concept, а не законченный продукт. Чего только стоит блокирующая передача данных по UART: один порт передает, остальные ждут. Нет, этот микроконтроллер определенно заслуживает большего! Пришлось засучить рукава и написать прошивку самому.

 

Что у меня получилось

 

Я решил по-максимуму задействовать возможности периферии микроконтроллера, но вместе с тем не впадать в пучину предварительных оптимизаций. Читаемость и поддерживаемость кода для меня гораздо важнее, чем незначительный прирост производительности. Тем более, что с производительностью и так все вышло очень хорошо.

 

Что реализовано:

 

 

Командный интерпретатор позволяет настраивать следующие параметры:

 

 

Командный интерпретатор активируется на первом CDC порту при подключении пина PB5 к земле, поддерживает часть управляющих последовательностей ANSI (стрелочки, backspace), и принимает вполне дружелюбные на вид команды:

 

*******************************
* Configuration Shell Started *
*******************************>uart 1 tx output pp dcd active low pull up
>

 

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

 

Распиновка вышла следующей:

 

Signal Direction UART1 UART2 UART3
RX IN PA10 PA3 PB11
TX OUT PA9 PA2 PB10
RTS OUT N/A PA1 PB14
CTS IN N/A PA0 PB13
DSR IN PB7 PB4 PB6
DTR OUT PA4 PA5 PA6
DCD IN PB15 PB8 PB9
RI IN PB3 PB12 PA8

 

Пины, выделенные жирным шрифтом, являются толерантными к 5 В.

 

К сожалению, реализовать RTS/CTS на UART1 не вышло из-за того, что соответсвующие пины заняты сигналами USB. Можно было вывести RTS на какой-нибудь другой пин, поскольку RTS управляется программно, в зависимости от степени заполнения кольцевых буферов на прием, но порт c RTS и без CTS мне показался странной штукой и я решил, что так делать не надо.

 

Проект написан на языке C, и подразумевает использование arm-none-eabi-gcc для сборки. Я использовал специфичный для GCC синтаксис атрибутов и расширения языка С. Совместимость проекта с проприетарными компиляторами меня не интересует, но если кто-то считает это важным, то я готов принять соответствующий пул-реквест.

 

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

 

Подробная документация, исходный код и собранная прошивка доступна в репозитории проекта на GitHub.

 

Дальнейшие планы

 

Нет предела совершенству и этот проект – не исключение. В каких-то местах код можно было написать чище, понятнее и эффективнее. Я обязательно этим в какой-то момент займусь. Кроме того, я очень рассчитываю на обратную связь от пользователей для поиска и устранения возможных багов.

 

UPDATE: добавил поддержку сигнала RI на всех портах (спасибо plyatov).

https://habr.com/ru/post/530060/