Jump to content

    
r2axz

Полноценный адаптер USB-Serial с 3 UART портами на STM32 Blue Pill

Recommended Posts

Доброго времени суток,

хотел поделиться своим проектом 3-x портового USB-Serial адаптера для STM32 Blue Pill (STM32F103C8T6).

Зачем все это, есть же куча USB-Serial преобразователей на любой вкус? Во-первых, это дешево. Плата Blue Pill стоит на али порядка 120 руб. Во-вторых, много портов в одном USB устройстве. Не занимаются лишние USB порты, нет нужды использовать USB-хабы. В-третьих, реализованы управляющие сигналы, не каждый USB-Serial преобразователь это умеет. В-четвертых, это гибко уже сейчас минимальным изменением исходного кода можно переключить тип выхода, полярность сигнала и т. п., а в будущем все это будет еще проще (см. ниже). В-пятых, это предсказуемо, повторяемо и документировано. Лично я не раз натыкался на не определяющиеся и некорректно работающие преобразователи c али.

Что реализовано:
- 3 независимых UART;
- поддержка аппаратного флоу контрола (RTS/CTS);
- поддержка DTR/DSR/DCD;
- 7 и 8 бит данных;
- поддержка контроля четности (none, even, odd);
- 1, 1.5, 2 стоповых бита;
- поддержка всех стандартных скоростей;
- поддержка нестандартных скоростей (тестировал до 921600);
- DMA на передачу и прием;
- не требует драйверов, используются CDC Class драйвера встроенные в ОС;
- составное USB устройство, определяется как три COM (tty) порта;
- подписанные драйвера для Win XP, 7, 8 (не требуется для Win 10);

Тестировалось на Win XP, 7, 8, 10, Linux, Mac OS.

Выходные уровни совместимы с TTL 3.3 и 5 вольт. Все входы кроме UART2 RX и CTS толерантны к 5 вольтам.

Маленькая ложка дегтя: по неизвестной причине, на некоторых экземплярах платы Blue Pill установлен некорректный подтягивающий резистор на USB D+. Это приводит к тому, что некоторые компьютеры эту плату не видят. А некоторые другие видят. Лечится заменой подтягивающего резистора на резистор номиналом 1.5 кОм. После этого все прекрасно работает на всех компьютерах.

Проект с открытым исходным кодом, MIT лицензия. Нет зависимостей от HAL или любых других сторонних библиотек кроме CMSIS.

Исходный код и собранная прошивка доступны тут: https://github.com/r2axz/bluepill-serial-monster

Что дальше? В планах добавить возможность конфигурирования типов выходных сигналов (пушпул, открытый сток), типов подтяжки сигнальных линий (floating, up, down) и выбора полярности (active-high / active-low) без пересборки ПО и перепрошивки микроконтроллера. Это позволит более свободно применять устройство с различными схемами развязок, согласования уровней, управления реле, и т.п.

 

Share this post


Link to post
Share on other sites
15 hours ago, r2axz said:
...
- поддержка нестандартных скоростей (тестировал до 921600);
...
Выходные уровни совместимы с TTL 3.3 и 5 вольт. Все входы кроме UART2 RX и CTS толерантны к 5 вольтам.

по процитированному выше:

- И что, все три порта в полном дуплексе успевают на 921600  транслировать потоки, без использования flow control?

- TTL уровни в многопортовке не очень интересны. Обычно много портов используется со стандартными уровнями интерфейса.

 

А в-общем, интересно, но непонятно как использовать :)  Как учебный материал- отличная тема.

Для себя лично вижу применение- добавить RS-232/485/422 драйвера, может даже с гальванической развязкой, и тогда будет хорошая штучка.  Коробочка такая с USB хвостом и тремя DB9 разъемами.

Share this post


Link to post
Share on other sites
2 hours ago, Ruslan1 said:

- И что, все три порта в полном дуплексе успевают на 921600  транслировать потоки, без использования flow control?

Короткий ответ: успевают, тестировал три порта одновременно в режиме loopback, скорость на каждом порту около 100 килобайт / сек.

Но вопрос не вполне корректный. Дело в том, что все зависит не только от производительности stm32f103c8t6, но еще и от того, насколько бодро хост будет забирать данные из IN эндпоинтов. Последнее же зависит от того, насколько бодро приложение использующее COM порт, будет оттуда эти данные вычитывать. Пример: у программы Tera Term открытие какого-нибудь UI диалога останавливает чтение из COM портов. Если в этот ком порт что-то сыпется снаружи, что остается делать устройству? Правильно, устройство буферизирует пока может, ну а потом дропает буфер и сообщает хосту через Interrupt Endpoint, что извини друг, случился buffer overrun. Все в точности как предусмотрено стандартом USB CDC ACM.

Поэтому в-целом, работа на высоких скоростях без flow control хоть и возможна (stm32f103c8t6 и моя прошивка тут не являются узким местом), но является сомнительной идеей по причинам изложенным выше.

2 hours ago, Ruslan1 said:

- TTL уровни в многопортовке не очень интересны. Обычно много портов используется со стандартными уровнями интерфейса.

Может быть именно под ваши задачи TTL уровни не интересны. А мне вот как раз интересны именно TTL. А кому-то еще, как вы выше уже заметили, может быть нужна опторазвязка. И так далее... И заранее не угадаешь ведь... Поэтому все эти детали, они out of scope, не являются частью проекта. Проект был о том, чтобы взять самую дешманскую железку и сделать на ней приличного качества преобразователь USB-Serial. А дальше уже подключайте к нему все что угодно, по условиям задачи.

Share this post


Link to post
Share on other sites
25 минут назад, r2axz сказал:

Поэтому в-целом, работа на высоких скоростях без flow control хоть и возможна (stm32f103c8t6 и моя прошивка тут не являются узким местом), но является сомнительной идеей по причинам изложенным выше.

Почему "сомнительной"? На тератерм свет клином не сошёлся. Есть множество других терминалок. Да и не обязательно пользоваться чужой прогой, можно и самостоятельно работать с COM-портом через WinAPI и никто не будет ограничивать скорость работы с ним (кроме собственных кривых рук канеш).

Вообще: я например 921600 бод использую по дефолту во всех своих устройствах для отладочного терминала (естественно - за исключением тех редких, где её не позволяют технические возможности аппаратуры).

Цитата

Проект был о том, чтобы взять самую дешманскую железку и сделать на ней приличного качества преобразователь USB-Serial. А дальше уже подключайте к нему все что угодно, по условиям задачи.

Имхо - вполне полезный проект. Кому-то пригодится. И спасибо Вам за труды! :smile: (хотя мне вроде пока это не нужно).

 

PS: Вдогонку (лень гуглить что именно позволяет "MIT лицензия" ;) - можно ли взять Ваши исходники и портировать их под другой компилятор и/или другую плату с STM32F103? Возможно с модификацией кода?

При условии, что результат потом также куда-то выложить.

 

PPS: Из предложений, могу добавить только, что неплохо было бы добавить светодиодную индикацию работы всех UART-ов (TX/RX/подключение_со_стороны_компа на каждый из COM-портов). И настройку с выбором конкретных пинов этого вынести в таблицу где-то в исходниках (чтобы каждый прошивающий мог под себя настроить их). Типа:

//                        порт,пин
#define PIN_LED1_TX       1,   6
#define PIN_LED1_RX       2,   7
#define PIN_LED1_CD       3,   8
#define PIN_LED2_TX       2,   0
#define PIN_LED2_RX       3,   1
#define PIN_LED2_CD       0,   2
#define PIN_LED3_TX       0,   5
#define PIN_LED3_RX       4,   5
#define PIN_LED3_CD       3,   5

 

Share this post


Link to post
Share on other sites
42 minutes ago, r2axz said:

Проект был о том, чтобы взять самую дешманскую железку и сделать на ней приличного качества преобразователь USB-Serial. 

Тоже считаю весьма полезным проектом !!!

А вот еще хорошо бы было получить преобразователь Ethernet-Serial и чтобы в компьютере виделся как COM порт или несколько COM портов. :blush:

Share this post


Link to post
Share on other sites
5 minutes ago, jcxz said:

Почему "сомнительной"? На тератерм свет клином не сошёлся. Есть множество других терминалок. Да и не обязательно пользоваться чужой прогой, можно и самостоятельно работать с COM-портом через WinAPI и никто не будет ограничивать скорость работы с ним (кроме собственных кривых рук канеш).

Вообще: я например 921600 бод использую по дефолту во всех своих устройствах для отладочного терминала (естественно - за исключением тех редких, где её не позволяют технические возможности аппаратуры).

"Сомнительной" потому, что ничего не мешает операционной системе пойти заниматься своими делами вместо чтения данных из USB. Только поэтому. Я тератерм привел просто в качестве примера. А так, даже самописной терминалке могут просто не дать процессорного времени. Но вы правы в том смысле, что почти всегда будет просто ломовой запас производительности со стороны хоста и проблем никаких не будет. Сквозной flow control приводит ситуацию к виду "всегда все будет в порядке", а его отсутствие оставляет нас в ситуации "почти". Но опять же, я согласен, очень часто (почти ( :) ) всегда) этим можно пренебречь.

13 minutes ago, jcxz said:

Имхо - вполне полезный проект. Кому-то пригодится. И спасибо Вам за труды! :smile: (хотя мне вроде пока это не нужно).

Спасибо за теплые слова!

13 minutes ago, jcxz said:

PS: Вдогонку (лень гуглить что именно позволяет "MIT лицензия" ;) - можно ли взять Ваши исходники и портировать их под другой компилятор и/или другую плату с STM32F103? Возможно с модификацией кода?

При условии, что результат потом также куда-то выложить.

MIT лицензия позволяет вам всё :) Можете копировать, изменять, использовать в других программных проектах или устройствах, продавать, и так далее. Вы не обязаны открывать свой исходный код при этом. Хотите выкладывайте, хотите - нет. Это дело ваше. Единственное, к чему MIT лицензия вас обязывает - это включить текст лицензии в состав дистрибутива и/или исходного кода если вы его распространяете. Потенциально с указанием к какому куску проекта она относится.

27 minutes ago, jcxz said:

PPS: Из предложений, могу добавить только, что неплохо было бы добавить светодиодную индикацию работы всех UART-ов (TX/RX/подключение_со_стороны_компа на каждый из COM-портов). И настройку с выбором конкретных пинов этого вынести в таблицу где-то в исходниках (чтобы каждый прошивающий мог под себя настроить их). Типа:

У меня нет на это свободных ног :) Вот это занято уже сейчас...

| 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**    |

Подключение ПО со стороны компа в USB CDC ACM в общем случае не определяется. А что касается состояния ног, если надо визуализировать, то что мешает подключить светодиод прямо на интересующую ногу через буфер?

11 minutes ago, dimka76 said:

Тоже считаю весьма полезным проектом !!!

Благодарю!

11 minutes ago, dimka76 said:

А вот еще хорошо бы было получить преобразователь Ethernet-Serial и чтобы в компьютере виделся как COM порт или несколько COM портов. :blush:

Ох... Если делать с нуля, то тут очень приличное количество возни с написанием драйверов. Но вроде гуглятся существующие продукты на эту тему которые могут работать с любым ком портом, просто пробрасывают его по IP и все. Денег правда стоят...

Share this post


Link to post
Share on other sites
1 час назад, r2axz сказал:

Подключение ПО со стороны компа в USB CDC ACM в общем случае не определяется.

Вероятно, иначе как по DTR это и не сделать...

1 час назад, r2axz сказал:

А что касается состояния ног, если надо визуализировать, то что мешает подключить светодиод прямо на интересующую ногу через буфер?

При очень коротких пакетах на большой скорости слишком уж слабая засветка. Но, с другой стороны, аналогичная индикация у FT2232 наоборот, не дает возможности адекватно оценить объем передаваемых/принимаемых данных (хотя это нужно очень изредка). 

Да, а когда совсем уж плохо с ногами под индикацию - 595 очень помогают. Но две-три ноги придется им отдать...

 

 

Share this post


Link to post
Share on other sites
8 minutes ago, rx3apf said:

Вероятно, иначе как по DTR это и не сделать...

Ну у меня DTR используется как выходной сигнал, которым предполагается управлять. И предполагается, что ПО может этот сигнал дергать туда сюда по своему усмотрению. Поэтому в качестве индикации именно подключения - так себе получается.

13 minutes ago, rx3apf said:

При очень коротких пакетах на большой скорости слишком уж слабая засветка. Но, с другой стороны, аналогичная индикация у FT2232 наоборот, не дает возможности адекватно оценить объем передаваемых/принимаемых данных (хотя это нужно очень изредка). 

Да, а когда совсем уж плохо с ногами под индикацию - 595 очень помогают. Но две-три ноги придется им отдать...

Да вариантов сделать такую индикацию масса, я понимаю. От чисто схемотехнических (поставить какую-нибудь времязадающую цепь которая даст нужную продолжительность горения светодиода) до программных, со сдвиговым регистром. И тут опять начинается вопрос "что-кому-надо-для-конкретного-проекта". Я все таки думаю не городить огород пока, а оставить индикацию как есть: базово активность по USART можно увидеть с помощью статусного светодиода (он строго говоря показывает активность USB, но одно приводит к другому). Да по всем трем портам вперемешку, да не видно состояния управляющих линий (но вообще их видно в ПО должно быть). Но зато не требует подключения к плате ничего лишнего. Я запишу себе в бэклог вопрос индикации, но вот прям сейчас не вижу как его можно решить именно "универсально".

Share this post


Link to post
Share on other sites
13 минут назад, r2axz сказал:

. Поэтому в качестве индикации именно подключения - так себе получается.

Да, само собой. Но если терминалкой (тот же TeraTerm) - DTR поднимается при открытии порта и деактивируется пи закрытии, так что достаточно адекватно.

 

13 минут назад, r2axz сказал:

 Я запишу себе в бэклог вопрос индикации, но вот прям сейчас не вижу как его можно решить именно "универсально".

Да и не надо - если кому так приспичит, пусть сам и дописывает. По возможности SPI зарезервировать бы под индикацию (а то и управление какими-нибудь некритичными по времени сигналами), но и только. И да, аппаратный вариант с одновибратором на RX/TX - вполне годное решение.

Ну, может быть (на будущее) еще подумать на предмет управления трансиверами RS-485 (так, как обычно делают, типично довольно коряво, это лучше иметь на "аппаратном" уровне).

 

Share this post


Link to post
Share on other sites
25 minutes ago, rx3apf said:

Ну, может быть (на будущее) еще подумать на предмет управления трансиверами RS-485 (так, как обычно делают, типично довольно коряво, это лучше иметь на "аппаратном" уровне).

Спасибо, запишу тоже в бэклог. Либо в рамках этого проекта, либо на будущее в другом.

У меня сейчас на самом деле в планах выкинуть один UART (это делается исключительно из-за аппаратных ограничений USB в конкретном MCU) и на освободившееся место приделать аудиокарту. На прием - встроенный ADC 12-бит, на передачу - PWM. И получится копеечный, но при этом вполне годный интерфейс для работы с digimodes (FT8 и всякие такое). Собственно этот проект USB-Serial - это побочный продукт большего проекта))) В первую очередь буду занят именно этим. А там поглядим.

Share this post


Link to post
Share on other sites

Пожалуй что правильная мысль. Три UART - забавно, конечно, но много ли практического смысла ? Хотя "неполноценный" (под RS-485, RX/TX и направление) UART может быть как-то и смотрелся бы сбоку...

Еще что полезно - USB/I2C, USB/SPI,  менее полезно, но что может встретиться - USB/1-wire, USB/параллельный (но это больше для экспериментов), USB/WS2812 (но это уж совсем специфическое).

 

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

Edited by rx3apf

Share this post


Link to post
Share on other sites

В порядке бреда (а точней - ради разрешения спора) сделал 7 USB-CDC на одном STM32F103. Понятно, что из-за его малюсенького буфера USB, пришлось сильно ограничить буферы CDC. Но оно работало в простых тестах. Другое дело - что не нужно обычно так много.

Вот два CDC на одном МК вполне можно запилить: скажем, один для коммуникации с МК, второй — для каких-либо настроек или отладки.  Вот, кстати, подумал, что в моем переходничке CAN-USB можно было бы именно так разделить собственно работу с шиной и команды (при обильном потоке данных приходится набирать команды вслепую - по крайней мере, команду паузы).

Share this post


Link to post
Share on other sites
5 minutes ago, rx3apf said:

 

Пожалуй что правильная мысль. Три UART - забавно, конечно, но много ли практического смысла ? Хотя "неполноценный" (под RS-485, RX/TX и направление) UART может быть как-то и смотрелся бы сбоку...

Еще что полезно - USB/I2C, USB/SPI,  менее полезно, но что может встретиться - USB/1-wire, USB/параллельный (но это больше для экспериментов), USB/WS2812 (но это уж совсем специфическое).

 

Вообще встречаются такие проекты. Правда и проект с тремя последовательными портами был на GitHub тоже (https://github.com/satoshinm/pill_serial), но мама дорогая, какое же это говно... Во-первых, кроме RX/TX ничего нету, а во-вторых, там блокирующая работа с USART, карл! То есть, пока один порт пишет/читает, остальные ждут. Ну и ошибок там полно. Хотя последнее - беда общая, уверен, и у меня найдутся.

11 minutes ago, rx3apf said:

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

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

/*  rx */ { .port = GPIOA, .pin =  3, .dir = gpio_dir_input,  .pull = gpio_pull_up, .polarity = gpio_polarity_high },
/*  tx */ { .port = GPIOA, .pin =  2, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_alternate, .output = gpio_output_pp, .polarity = gpio_polarity_high },
/* rts */ { .port = GPIOA, .pin =  1, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low},
/* cts */ { .port = GPIOA, .pin =  0, .dir = gpio_dir_input,  .pull = gpio_pull_down, .polarity = gpio_polarity_low },
/* dsr */ { .port = GPIOB, .pin =  4, .dir = gpio_dir_input,  .pull = gpio_pull_up, .polarity = gpio_polarity_low },
/* dtr */ { .port = GPIOA, .pin =  5, .dir = gpio_dir_output, .speed = gpio_speed_medium, .func = gpio_func_general, .output = gpio_output_pp, .polarity = gpio_polarity_low },
/* dcd */ { .port = GPIOB, .pin =  8, .dir = gpio_dir_input,  .pull = gpio_pull_up, .polarity = gpio_polarity_low },

И поменять его может даже не умеющий программировать человек. А через конфигуратор можно задать тип подтяжки (вверх/вниз/без подтяжки), полярность сигнала (активный высокий/низкий) и тип выхода (пушпул/открытый сток). Конфигуратор доступен в виде шелла на первом порту когда PB5 замкнут на землю. Выглядит это так:

*******************************
* Configuration Shell Started *
*******************************

>help
help    - shows this help message, use "help command-name" to get command-specific help
config  - save and reset configuration paramters in the device flash memory
uart    - set and view UART parameters
>help uart
uart: set and view UART parameters
Usage: uart port-number|all show|signal-name-1 param-1 value-1 ... [param-n value-n] [signal-name-2 ...]
Use "uart port-number|all show" to view current UART configuration.
Use "uart port-number|all signal-name-1 param-1 value-1 ... [param-n value-n] [signal-name-2 ...]"
to set UART parameters, where signal names are rx, tx, rts, cts, dsr, dtr, dcd,
and params are:
  output        [pp|od]
  active        [low|high]
  pull          [floating|up|down]
Example: "uart 1 tx output od" sets UART1 TX output type to open-drain
Example: "uart 3 rts active high dcd active high pull down" allows to set multiple parameters at once.
>uart 1 tx output od
>config save
>

 

Кстати, установив uart 1 tx output od и соединив RX c TX получаешь халявный CI/V для ICOM (проверял с 706).

Возможно я не прав и стоит сделать переназначение для ног из конфигуратора. Я еще подумаю. Ну и RX/TX/CTS особо не переназначишь. Что-то конечно с remap можно придумать. Но это имхо оверкил.

Just now, r2axz said:

Как вариант - AT-командами на одном из портов, в особом режиме.

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

Share this post


Link to post
Share on other sites
59 minutes ago, rx3apf said:

Три UART - забавно, конечно, но много ли практического смысла ?

В промышленной автоматике и больше портов используется.

Вот пример

https://moxa.pro/catalog/nport5650-16

Share this post


Link to post
Share on other sites
53 минуты назад, r2axz сказал:

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

Но не делать же ради этого полноценный встроенный конфигуратор a la ANSI терминал ? (Было бы красиво, но очень уж избыточно). Можно же тупо регистр = значение. Прочитать/записать/справка по синтаксису (без подробностей). Впрочем, это дело совершенно "хозяйское" (потому и говорю - в порядке бреда ;)

22 минуты назад, dimka76 сказал:

В промышленной автоматике и больше портов используется.

 

Да, само собой. Да хоть бы и FT4232 на четыре порта. Но три - ни то, ни се, да и в повседневной жизни редко может пригодиться. А вот два - нужно часто. Два плюс RS485 - тоде вполне представляю применение. Ну, тут у каждого свое видение, по своим задачам....

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.