Как стать автором
Обновить
19
Карма
0
Рейтинг

Пользователь

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

Исправлено в версии 2.3.3, пожалуйста, обновитесь.

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

Мне интересно именно ADC и ШИМ попробовать. Может и не заработают. Посмотрим. По поводу зависания — интересно, попробую повторить. А на какой ОС вы работаете?

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

Кстати, по поводу ваших "граблей" в статье. Я посмотрел ваш код на GitHub и мне бросилось в глаза, что у вас USART RX настроен как floating. А он должен быть подтянут к Vcc. И тогда все будет хорошо, не будет никакого "мусора" и не надо будет запрещать прием на время передачи.

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

Я не остановился и довел задержку до 0.6 мкс. Вот на этом пока остановлюсь :)

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

Я вряд ли буду это делать. У меня в планах выкинуть один из последовательных портов и попробовать добавить туда простенькую аудиокарту: один вход с использованием ADC, один выход с использованием таймера в режиме ШИМ. И тогда получится интерфейс для радиолюбительских трансиверов, для работы во всяких цифровых модах типа FT8. Но пока сложно сказать, когда я это сделаю.

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

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

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

Довел время сброса TXA до 0.6 мкс применив bit banding. Теперь еще больше шансов, что все заработает на 460 кБод на трех портах одновременно.

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

Я постарался (и продолжаю стараться) сделать обработчик прерывания от USART как можно более коротким, и с хорошей вероятностью все будет работать на 460 кБод на 3-х портах одновременно. Но мне всё-таки нужно больше обратной связи от тех, кто будет это использовать в реальной жизни. Просили сделать RS-485 — я сделал. Теперь я, в свою очередь, прошу протестировать результат :)


<зануда моде он>
Бод = это бит/с, поэтому бод/с — это не скорость, это ускорение :)
</зануда моде офф>

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

Добавил поддержку RS-485, обновил статью.

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

У STM32F072 и STM32F103C8T6 разные USART. У первого есть режим в котором сигнал RTS может управлять DE(/RE) RS-485, а у второго — нет. В целом, USART на STM32F072 более продвинутый. Но что поделать, ведь STM32F103C8T6 гораздо более распространен и дешев, поэтому выбор очевиден.


Что касается граблей, то насколько я понял все грабли у вас заключались в том, что 5-ти вольтовый MAX485 то ли работал, то ли нет с 3.3 вольтовыми уровнями (или питанием?). Или я что-то пропустил? Может в комментариях?


В-общем, я пока работаю над софтовым управлением TXA (DE, /RE). Пришлось перепахать всю прошивку, отказаться от прерываний USB в пользу поллинга, задействовать вытесняющие прерывания и много всего по мелочи. Когда-нибудь потом напишу статью об этом.


А пока задержка переключения TXA по окончанию передачи составляет менее 1 мкс. Измерено осциллографом на одном из портов на фоне занятых постоянной передачей двух других. Это позволяет работать с RS-485 на скоростях не менее 460 кБод и на мой взгляд, это очень прилично. Хотя я собираюсь еще немного ужаться.

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

Сделал экспериментальную версию, обновил статью.

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

Спасибо, не знал про U-620. Мощная штука! Но мне не подходит: мне в первую очередь требуются TTL уровни.

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

Спасибо! Я не стал выделять конфигурацию в один порт для того, чтобы не терять в производительности. Хотя, здесь есть пространство для дебатов. Дело в том, что в stm32f103c8t6 размер USB packet buffer memory равен 512 байтам. 112 из них заняты buffer description table (для 7 endpoints), сами endpoints занимают еще 384 байта. При этом, уже даже тут пришлось несколько ужаться, и размеры BULK IN/OUT endpoints для порта 1 сделать равными 32 байтам против 64 байт у остальных портов. Это несколько ограничивает производительность первого порта. Таким образом, у нас осталось всего 16 байт, которые все и уйдут на дескриптор 8-го endpoint. Надо откуда-то взять еще хотя бы 16 байт. В принципе, можно уменьшить два из трех INTERRUPT IN endpoints до 8 байт и передавать уведомления о состоянии порта за два «захода». Но мне не захотелось так делать вот почему: конфигурационный порт нужен далеко не всем и используется относительно редко. Я не захотел выделять для него на постоянной основе ресурсы, которые могут помочь увеличить производительность при нормальной работе.


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


С другой стороны, пока я все это писал, я понял, что у меня есть аж 16 свободных байт, а текущий размер control EP0 – 8 байт. Будет лучше инвестировать эти свободные байты туда.

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

Софтовая реализация RS-485 могла бы быть отличными упражнением, но для практического применения боюсь будет слишком медленно. Особенно, если надо сделать больше одного порта.

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

Есть разница между конструктивной критикой и "бла-бла-бла, в вашем коде не хватает комментариев, поймет только компилятор, а автор все забудет через год". Первое — приветствуется, второе — неприемлемо. А комментарии в стиле: "но с указателями и типами данных у вас помойка в коде. Ищите сами." — это вообще ни о чем. Однако, если бы вы написали что-то в стиле: "вот тут сделано неправильно потому-то и потому-то", то я сказал бы вам огромное спасибо. Если бы вы написали "в таких условиях возникает вот такая ошибка, повторять так", я бы вообще прыгал до потолка от радости. Конечно, если бы это было действительно неправильно и у меня не было бы причины сделать именно так.


  1. Валить все на конфигуратор не стоит, CubeMX и не такую еще дичь генерит, но это не значит что его использование является обязательным. А в WinAPI как раз очень разумная, не близкая мне лично, но разумная политика названия переменных;
  2. Правильно, но не в том месте в котором она вызывается. Кончится это тем, что один программист поправит функцию инициализации, а вот про все места из которых она вызывается даже не подумает. А другой программист потом будет очень рад, потратив пару часов на осознание того факта что в комментарии написано одно, а функция делает другое.
  3. Традиция, так традиция. Но мне-то какое дело до ваших традиций?
  4. Опять же, тот факт, что у вас что-то оформлено в стиле SiLabs никак не делает ваши дескрипторы более читаемыми. Хотя да, я понимаю, есть еще возможные ограничения компилятора.

А камень в ваш огород я не кидал, я просто указал на конкретные проблемы вашего стиля кода и комментирования, со ссылками на конкретные места в вашем коде, объяснил к чему это потенциально приводит.


И я правда не считаю ценными советы по оформлению кода от человека с таким качеством кода как у вас. Покажите пример, а если нет — тогда действительно, вы все сделали правильно удалившись из темы.

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

Да, тогда понятно. Вы правы, без драйвера никак.

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

По USB? А что еще с этими данными происходило? Чем еще прошивка занималась, расскажите, пожалуйста. Это интересно!

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

У нас с вами разный подход к комментированию кода. Я считаю, что сам код должен быть написан так, чтобы был понятен без комментариев. От этого у меня в коде длинные и осмысленные названия имен переменных, функций и так далее. Комментарии я использую для описания важных и неочевидных вещей, когда это действительно требуется, а также для отделения логических блоков в коде друг от друга. До сих пор я как-то умудрялся разбираться в своих проектах даже 20 летней давности. И другие люди тоже разбирались без проблем. А еще есть blame в Git и commit messages…


А если уж совсем позанудничать...

То я посмотрел код вашего проекта MIDI2USB, давайте для примера возьмем main() из main.c


WDT_Init();            // Disable WDTimer (not used)
PORT_Init();            // Initialize ports (UART, LEDs)
SYSCLK_Init();            // Set system clock to 48MHz
UART0_Init();            // Initialize UART0 @31250, 8-N-1
USBD_Init( &usbInitStruct );            // Initialize USB, clock calibrate
LED_IN  = 1;            // Blink LED
LED_OUT = 1;            // Blink LED
IE_EA   = 1;            // Global enable IRQ

Если у вас функция WDT_Init не инициализирует watchdog, а запрещает его, функция PORT_Init() инициализирует не порт, а порты и так далее, то да, такой код лучше комментировать.


Я уже не говорю о том, какие проблемы бывают при расхождениях в коде и комментариях. И о том, что код вызывающий UART0_Init() не должен и не может знать о том что это на самом деле "// Initialize UART0 @31250, 8-N-1" в случае если он не передает эти параметры явно при вызове функции.


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

Информация

В рейтинге
5,805-й
Зарегистрирован
Активность