Как стать автором
Обновить

Комментарии 105

Наконец-то! Спасибо большое!!!
Да все никак времени не было. На статью ушло больше 4 часов плюс сам проект подготовить к публикации.
Надеюсь будет полезна.
Лучше уж тогда в TCP сразу
Если вы об Ethernet функционале, то его в STM32F103 нет.
Ну понятное дело, просто мы в свое время долго с разными такими конвертерами возились и в итоге отошли в пользу Serial-IP конвертеров, как наиболее стабильных и предсказуемых.
есть у меня такой. Еще не возился с ним. Но я говорю в статье об элегантном способе взаимодействия с ПК. Без дополнительных микросхем, конвертеров и лишних задержек. Максимально нативный интерфейс для современного компьютера. К тому же МК с поддержкой USB экстремально дешевы.
TCP/IP нельзя назвать ни простым ни дешевым ни быстрым протоколом. Особенно в вариации со всякими промежуточными конвертерами.
Для специфических случаев, когда нужно передавать данные удаленно — это то, что нужно. А при локальном подключении — удобнее USB. Никакой возни с сетевыми адресами, все прозрачно и автоматически. Для пользователя — жутко удобно. А для промышленного применения вообще лучше CAN. Но там без CAN трансивера не обойтись.
>TCP/IP нельзя назвать ни простым ни дешевым ни быстрым протоколом.

На фоне изначального посыла о том, как хорош COM-порт это несколько слишком сильное заявление.

Как и утверждение о том, что " для промышленного применения вообще лучше CAN".

Ну и с локальным подключением не все так розово и пушисто. 3 метра или 5 метров — это локально или уже удалённо?
Я не говорил, что COM порт хорош. я говорю о том, что у него много приверженцев. Ну нравится он людям, что тут поделать. Я не очень любли потоки. Предпочитаю пакеты. Но у меня для этого свои причны.
>3 метра или 5 метров — это локально или уже удалённо?
Тут все определяется стандартами. 5 метров для USB — допустимо, но кабель нужно очень качественный. Да и питание по нему подавать уже нежелательно. Вообще же граничные случаи на то и граничные, чтобы рассматривать их более внимательно и с учетом остальных факторов.
Ну, у вас пост начинается с COM-порта и кабеля USB-to-COM… кстати, неработающего (это который блестючий), так что дальше невольно про COM помнишь…

>Ну нравится он людям, что тут поделать. Я не очень любли потоки. Предпочитаю пакеты.
а какие проблемы обмениваться пакетами по COM/UART? Я, честно говоря, тезиса «потоки vs пакеты» не понимаю.
Если я правильно понял автора, то он имеет в виду под «потоком» тот (довольно неприятный) факт, что из последовательного порта данные считываются в режиме «байт за байтом» в, условно говоря, бесконечном цикле. И проверка «пришел ли уже весь пакет данных или дальше ждать?» осуществляется в момент приема каждой порции. И порция может содержать данные и для двух (или более) пакетов, и надо реально байт за байтом в ней рыться…

А в случае пакетной передачи по USB ресивер просто получает сообщение «пакет пришел целиком».
Именно так. Это очень существенный недостаток потоков. Бесконечный цикл не обязателен — есть прерывания. Но это никак не упрощает задачу.
> И порция может содержать данные и для двух (или более) пакетов

позвольте, такая фигня происходит только в том экзотическом случае, когда наши люди вешают на один COM-порт несколько устройств, или в еще более экзотическом случае, когда «с другой стороны» вешают многозадачный PC с необсемафоренным обменом.
А во всех остальных случаях — создать пакет с заголовком, длиной, данными и контрольной суммой — плевое дело. А если участь аппаратные буферы на 16 байт и в PC и в МК и буфер драйвера в PC, да смешные по нынешним временам скорости обмена…
Выявление в потоке пакета — это дополнительная задача, требующая буферизации, выявления начала и конца пакета, проверки на целостность, введения доп. символов в поток для надежного определения заголовка. Все это надо программировать, это ест ОЗУ, ресурсы МК и время программиста. Если вы всего этого не делаете — обмен нельзя считать надежным. Пакетный обмен в USB все это делает прозрачно для программиста. Все данные уже разложены по нужны полям пакета, просто рассматриваешь полученный пакет как struct. Это ОЧЕНЬ удобно. При отправке то же самое — достаточно записать данные в поля структуры простым присваиванием и отправить буфер одной командой. Об остальном позаботится модуль USB. Причем буферы у него аппаратные.
Если вам это непонятно, то либо вы не делаете всего этого, что вообще-то странно, либо вам нравится каждый раз изобретать велосипед.
При работе с пакетами переменной длины в потоке нужно вводить какие-то идентификаторы длины пакета, выяснять считан ли весь пакет, не пропали ли байты и т.п.
При работе же с пакетами в USB достаточно определить какие поля нужны и какого размера. Это вся подготовка к работе.
>Выявление в потоке пакета — это дополнительная задача, требующая буферизации, выявления начала и конца пакета,
очень сложная задача, ага.

Сколько лет функции gets(), напомнить?
— Нет, я конечно понимаю, что вы имеете ввиду случай, когда много устройств сидят на одной шине, но это не случай COM/UART в стандартном виде.

> Все это надо программировать, это ест ОЗУ, ресурсы МК и время программиста.
насчет ресурсов и ОЗУ в МК — ровно наоборот, достаточно собрать пример «хеллоу ворлд» для UART и для USB.

>USB. Причем буферы у него аппаратные.
вы не поверите, у UARTов тоже
Нет, вы не понимаете. Речь вовсе не о том, что несколько устройств на одной шине.
Кроме того — текстовый протокол в обмене между устройствами я считаю глупостью. Я его все равно читать не буду, а для девайса экономнее и быстрее использовать двоичный протокол.
Большинство проектов для МК вообще не включают реализацию обработки строк. Если от устройства не требуется выводить текст для человека, то это лишний расход ОЗУ, flash памяти и процессорного времени.
К тому же алгоритм обработки текста всегда более неуклюж чем для бинарных данных.
Я никого не призываю поступать именно так. Нравится вам заниматься половину времени над проектом всякой посторонней работой, не влияющей на результат — на здоровье, пишите протоколы и обработку потоков.
Я их уже написал для себя, но все равно использовать не люблю — родная поддержка пакетного обмена куда как элегантнее. Точно так же как не люблю дрыганье ножками для реализации протоколов типа SPI, I2C, и программный UART. У них всегда есть неудобства и программные ограничения, которые рано или поздно вылезают боком.
Правильно ли я понимаю, что в случае пакетного подхода в USB HID размер пакета строго фиксирован?

Но ведь тогда, справедливости ради, и через последовательный порт при использовании фиксированного размера пакетов данные читать не сильно сложнее. Зато вот сделать пакет произвольного размера в случае USB HID не получится, в отличие от…
Пакета с конкретным ID да, но идентификаторов может быть сотни, на каждый тип используемого пакета. А можете задать пакет максимального используемого размера сделать поле с идентификатором своего типа пакета, который позволит рассматривать его как нужного формата структуру.
При использовании последовательного порта — сильно сложнее. Вообще говоря программа нелинейная, поэтому по приходу каждого байта нужно анализировать не только его, но и байты до него, уже находящиеся в буфере, а также вводить машину состояний — принимаем пакет, ждем пакет, ждем поле длины пакета, ждем контрольную сумму, ой, пропустили из-за того, что кабель выдрали и снова вставили или питание девайса моргнуло и теперь мы принимаем с середины пакета. Я в свое время занимался разработкой системы телеметрии и телеуправления Ташметрополитена и у меня было 13 географически распределенных стоек с оборудованием, связанных модемами USRCourier. Кабельные линиии были не лучшего качества, помехи, возможные потери байт, а тайминг на весь цикл опроса станций и ответа — не более 4с. Вместе с повторами.
Сейчас такое легко встречается при наличии помех по питанию, наводок от моторов рядом (управление станком ЧПУ, например) и т.п.
В академическом случае на столе все работает хорошо. Но протокол должен быть надежным и если часть этой работы можно выполнить аппаратно, лучше делать ее аппаратно. К тому же это проще и удобнее.
Кстати, комментарии для того и нужны, чтобы учиться друг у друга и обсуждать.
Если можете посоветовать набор библитек для пакетной связи через COM порт для Delphi + C/C++ на ПК + С/С++ на МК, чтобы обмен был бинарным, с задаваемым размером пакета и передать было достаточно указатель на буфер и размера буфера, остальное библиотека должна сделать сама. По приему пакета она должна вызвать мою функцию для обработки принятого пакета. Если будут функции, сигнализирующие об ошибках на линии — отлично.
Увы, готовую библиотеку порекомендовать не могу. В тех проектах, где я данные через последовательный порт читал, логику на стороне хоста сам реализовывал (обычно — в отдельном треде, в последнее время — с помощью Qt и механизма сигналов/слотов). А на стороне MK другие люди данные готовили, уж и не знаю, как именно…
Вот именно, так обычно и бывает :) Библиотек много, а один фиг — вручную велосипедить.
Возможно, вам будет интересен протокол Modbus RTU.
Да, смотрел его. На мой взгляд его реализация немного геморройная — нужно мерять таймауты между символами, значит нужно кроме UART задействовать еще и таймер. А со стороны ПК вообще нет поддержки ни ModBus ни RS485. Поэтому применение — только в сети МК.
???

>Кроме того — текстовый протокол в обмене между устройствами я считаю глупостью.

Еще со времен модемов 1200 бод ээээ… дай бог памяти без MNP никаких проблем с нетекстовым обеном не было.

>Большинство проектов для МК вообще не включают реализацию обработки строк. Если от устройства не требуется выводить текст для человека, то это лишний расход ОЗУ, flash памяти и процессорного времени

еще раз повторю — вопрос расхда памятей решается сборкой проекта с использованием и неиспользованием и USB

>Точно так же как не люблю дрыганье ножками для реализации протоколов типа SPI, I2C, и программный UART. У них всегда есть неудобства и программные ограничения, которые рано или поздно вылезают боком.

оно давно уже аппаратное, в том же вашем STM32F103C8
Именно, поэтому и работа в пакетном режиме должна быть аппаратной, раз такая возможность есть. Если бы был модуль, который реализует всю грязную работу по пакетному обмену — я бы им пользовался. Для CAN и USB это делается средствами периферии аппаратно.
Вообще я предвидел, что основной спор будет на тему — UART vs HID :) типа «чем вам не угодил простой UART».
Так вот — каждый пользуется тем, что ему больше нравится. Я люблю комфорт и функциональность. Всем, кому это интересно, я предложил попробовать с минимальными усилиями. Если вам не нужно — пользуйтесь UART
>Вообще я предвидел, что основной спор будет на тему — UART vs HID :) типа «чем вам не угодил простой UART».

А чего тут спорить? Ваши возражения против UART, (как и Ethernet) несколько не соответствуют реальности. Только и всего. Совершенно не в плане религиозных войн.
Всякий интерфейс имеет свою область применимости. Вот у меня, например, в одном из проектов после дрыгания одной ногой через 6 мкс я с другой ноги считываю 10 байт, причем обе ноги — оптоизолированные. Могу ли я сделать что-то аналогичное с USB? Очевидно, что не могу, хотя бы потому что для USB задействовано больше ног ;-)
А причем тут USB? Ну получили вы свои 10 байт, а данные ПК как отдать? вот тут придет очередь USB. Пакуем их в пакет и отправляем. Если надо, предварительно обрабатываем. Для того МК и нужен.
Не, USB не наш выбор ;-)
Или тот же ЦОМ-Порт, ибо так исторически сложилось, или эзернеты.
По крайней мере для околопромышленного применения, где видео не надо передавать, а вот думателем думать надо достаточно серьёзно и поэтому полученные за 6 мкс 10 байт никуда передавать не нужно, а вот всякие опторазвязки от напряжений и наводок очень сильно желательно.

Опять-таки — не в порядке религиозных войн, а только обмена опытом

Завязались в свое время на ethernet и в процессе отладки я попробовал через wifi цепляться к контроллеру, оказалось в целом жутко удобно и главное, что пропускной способности хватает и расстояние до девайса может быть значительным.
Я вот почитываю всякие статьи, обычно дело заканчивается классом HID. Вот задумался над классом CDC, в частности виртуальным COM-портом. Причем главным требованием является работа без использования сторонних драйверов, сейчас на винде писать свой драйвер геморрой (требуется подпись). Может кто-нибудь даст ссылочку на реализацию CDC класса виртуального COM-порта с использованием стандартного драйвера usbser.sys? Или объяснит, что с HID классом работать проще и удобней?
Виртуальный комп порт имеет недостаток — он работает в таком же пакетном режиме, а не в потоковом, как реальный COM порт, соответсвенно те же скорости и задержки. Но ко всему прочему потребует драйвер скорее всего. Под стандартный драйвер не видел реализаций.
На мой взгляд с HID работать гораздо приятнее и удобнее — никаких номеров портов, каждый девайс можно автоматически подцеплять при подключении к компу. Не нужно сканить порты на появление и исчезновение, не нужно пытаться аккуратно закрыть порт при отключении девайса. Можно подключать столько прог к одному девайсу, сколько нужно. Девайс сам поставляет данные по мере их наличия (прерываниями заниматся USB шина) а не приходится опрашивать по таймеру, в итоге получается, что софтина на ПК занята только обработкой полезных данных и ровно тогда, когда они появляются, а не по таймеру, пытаясь угадать как же часто нужно опрашивать устройство, чтобы скорость реакции была приличная и нагрузка не слишком возросла.
На мой взгляд для связи ПК-МК последовательный порт крайне редко бывает оправдан.
Поэтому я никак не могу понять этой инерции мышления — любой интерфейс превращать в убогую трубу с байтами, даже когда возможностей куда больше.
Здесь вопрос стоит так: как получить максимальную пропускную способность, при использовании стандартных USB драйверов Windows.
К слову, (реальная) максимальная пропускная способность USB куда выше, чем у UART (тот же STM32F103, если не ошибаюсь, максимально разгоняет USART до 8 мегабит, и то, вряд ли терминал ПК протащит такую скорость, и провод нужно очень короткий и экранированный). Для USB гораздо меньше проблем в этом плане (хотя и STM32 не будет работать в High-speed, Full-speed с потолком в 12 Мб/с он протащит без особых проблем). Только это уже не HID-устройство будет, как автор сказал, а несколько другое.

Как мне кажется, UART очень хорошо использовать внутрисхемно (для соединения нескольких чипов) и для соединения с ПК какого-нибудь простого контроллера (типа AVR; хотя туда есть программный V-USB, не всегда разумно его использовать). Где можно использовать USB — почему бы и нет? Вопрос только в том, насколько часто ваше устройство должно связываться с ПК (мне очень часто приходится делать устройства, которые после однократной настройки по тому же UART уходят в «свободное плавание», там городить USB-стек смысла не вижу).
A USB это все тот же UART только с одним финтом — применено специальное кодирование чтобы снизить частоту на шине в двое по сравнению с тем же UART при аналогичной битовой скорости. Проблема классического UART лишь в том что источник тактовых импульсов для него должен быть в 8-16 раз больше скорости передачи, естественно эта частота берется с тактовых импульсов контроллера.
Ну и узкое место — это линия передачи если приделать к UART драйвер симметричной линии, то расстояние передачи будет таким же как у USB на аналогичной скорости. Просто USB это дальнейшее развитие UART на которое навешали столько наворотов, что он уже сам на себя не похож и это только в аппаратной части.
А еще COM порт не дает нужных показателей скорости. Кстати, а как там дела у usb-hid? Или в случае необходимости большой пропускной способности только ethernet остается?
В случае необходимости в большой скорости можно использовать другие профили USB. Скоростные параметры шины давно известны.
Но, если мне память не изменяет, то для других профилей нужен vendor id, который не так то просто получить.
VendorID нужен в любом случае, особенно если вы делаете коммерческое устройство. Но есть приличное количество VID и PID которые безопасно можно использовать. Главное, чтобы устройство с такими идентификаторами не было.
Вроде мегабит ограничение протокола, да?
У самой USB шины как минимум 12 мБит.
А у масс-трансфера HID — 1Мбит
Да. Но никто не заставляет использовать именно HID, если нужная действительно высокая скорость. Реально это нужно крайне редко, там можно и над драйвером поработать
Забавно читать такие статьи в стиле «Все просто! 1. рисуем два кружочка, 2. рисуем остаток совы»

Под потоковый обмен уже столько готового софта (причем, кроссплатформенного) написано, что это не проблема совершенно. А вот как ваши пример под линукс адаптировать — придется голову поломать. Жаль, что создатели USB не предусмотрели профиля «дуплексный асинхронный сокет», хотя архитектура именно под него заточена.
Остаток совы за вас уже нарисован :) Так что осталось именно два кружочка нарисовать. Хотите разобраться во всем самостоятельно — вам не в статью для начинающих, но проект тоже может быть полезен для изучения.
Под потоковый обмен написано всего много, но почему то как доходит до дела, выясняется, что либо слишком тяжелая библиотека, либо не компилируется совместно с другим софтом, либо не умеет чего-то, либо работает без DMA, а надо с ним, либо неудобна в работе, либо лицензия не та. Проходили. В итоге все равно приходится изобретать велосипед. Каждый раз.
Я вот собирал проект для F3-Discovery: github.com/dccharacter/AHRS
Там можно дефайнами переключить проброску данных либо через HID-Joystick, либо через CDC.
Там же питоновский визуалайзер лежит: github.com/dccharacter/AHRS/blob/master/myVisualisation.py
За код ногами не бейте…
Ок, понял, что немного не в тему.
Ну почему же. Может кому пригодится.
Кстати, с алгоритмами Мэджвика и Махони есть взаимопонимание?
В смысле? Есть ли понимание, как они работают? Неа :-) Но знаю где почитать общую теорию АХРС-а. Суть понятна, чтобы вникнуть в детали нужно неплохое знание математики и тригонометрии. У меня, к сожалению, с математикой как у первокурсника после первого семестра — так себе…
С кватернионами вроде чуть-чуть разобрался — вон написал визуалайзер, но потом опять все позабыл… Тоже знаю где почитать.
Суть я и так знаю, не хватает именно понимания деталей. Где почитать про кватернионы?
Спасибо. С примерами кода гораздо лучше чем голая теория, которой обычно все и кончается.
Вопрос, наверное, глупый, но можно ли используя класс USB-HID реализовать отправку данный о паре десятков энкодеров и паре десятков кнопок и переключателей?

Интересуюсь с целью самостоятельной сборки:
image
Только без дисплеев.
Возможно и:
image
Так же без приборов и дисплеев
Без проблем. А что именно пытаетесь сделать, виртуальную кабину самолета?
Идей две —
1. Стенд для ВУЗа и ПО имитирующее работу определенной системы самолета, например для демонстрации запуска и опробования двигателей. Элементы управления снаружи, приборы через проектор.
2. Настольный вариант панели, чтобы связать с симулятором (XPlane, MS FSX)
Для этой задачи подходит идеально.
Кто-нибудь встречал в продаже готовые дополнительные кнопки? Интересуют:
  1. Отдельные большие кнопки (размером со спичечный коробок).
  2. Переключатель (2-х, 3-х позиционный) чтобы на ощупь определялась позиция, желательно с программным переключением положения. (под переключатель раскладки клавиатуры)
  3. Блоки по 4-5 кнопок в ряд небольшого размера (чтобы пальцами одной руки можно было нажимать)
Отдельные большие кнопки — точно бывают, обычно квадратные (такие ставят на всякие игровые автоматы).
Что имеется в виду под «программным переключением положения»? Переключатели бывают, движковые, например (на игрушках разных обычно ставят). У него позиция чётко видна, можно сверху более аккуратную ручку установить.
Вот про блоки кнопок — надо искать. Сейчас на ЧиДе посмотрю, там всё слишком дорого, конечно, но зато есть очень грамотный каталог, можно хотя бы представить, что бывает.
Под программным переключением я подразумеваю возможность задать положение кнопки из программы. Т. е. в кнопке должен быть какой-нибудь минимальный привод.
Ой, вот это точно в дефиците. Впрочем, кнопок я пока тоже не нашёл соответствующих, но есть прямая отсылка на китайских поставщиков типа dealextreme или satistronics.

Насчёт «программно переключаемого свитча» я бы предложил какое-нибудь touch-решение с led-индикацией, но для этого нужно либо самому разбираться, либо призывать радиолюбителей, кто с этим работал. Тут не помешает навык работы с МК, и всё зависит от того, куда всё это добро нужно подключать.
Возможно, кто-нибудь сможет подсказать, в каком документе можно узреть значения всех полей HID-дескриптора? В официальной документации я утонул, но ничего вразумительного не нашел.

Я пытаюсь сгенерировать самый тупой дескриптор для передачи 64 байт, но я никак не могу понять, какие поля нужно указывать? Нужно ли указывать и REPORT_SIZE и REPORT_COUNT? LOCAL_MAXIMUM — это максимум для одного байта или для всех?
Разумеется, все нужно указывать. Возьми за основу мой проект — там есть переменные
#define RPT3_COUNT 0x01 //PC->STM32
#define RPT4_COUNT 0x04 //STM32->PC

Они прописаны в дескрипторе.
Я, к сожалению, не могу прямо взять ваш проект, у меня плата с STMF407. Но вы же дескриптор не из пальца высосали? Поделитесь, чем вы пользовались, чтобы его составить, пожалуйста.
Дескриптор для любой платы одинаковый.
Читайте внимательно, я выложил все инструменты.
Вам нужен DT — HID Descriptor tool
Да, как-то не подумал, что можно только дескриптор взять. Спасибо.
HID Descriptor tool облегчает дело, спору нет, но из нее совершенно непонятно, какое поле что означает.
Это основная проблема usb вообще. Информации в доступном виде нет, сама шина очень сложна. Те описания, что есть- фрагментарны или очень запутаны. Поэтому я и предложил проект-шаблон.
То есть вы его по кусочкам собирали? Жаль, жаль.
Да, собирал по частям. Единого документа не встречал.
Интересно, как интерфейс с такой отвратительной спецификацией стал таким популярным. Жуть.
Классика же, сначала садим на иглу а потом все оказываются должны и отказаться нет возможности.
Спецификация отвратительная, зато возможности очень обширные, стандарт живет уже много лет и сохраняет обратную совместимость, аналогов у него с таким функционалом просто нет.
к эзернету только питание прикрутить на разъеме и новый стек при необходимости — получилось бы не хуже(при необходимости обеспечивать расстояние передачи больше 10м и можно было бы легко поднять скорость).
Если навесить на Ethernet функционал usb, автоопределение, автоконфигурацию, то usb и получится, только с неудобным разъемом.
А вы не поделитесь примером для stmf407?
Вот. Только пример custom hid я тут уже разворошил, а где оригинал брал — не помню.
Спасибо. Попробуем выковырять
Не поделюсь :) Потому что не писал для F407 этого примера. А писать с нуля вам столько же сколько и мне. Принцип тот же.
Уже выложили для discovery
А так у меня сейчас даже родные примеры от st не заводятся.
В системе не появляться новое usb устройство
У меня заводятся, но там есть косяк, который пока руки не доходят исправить — надо отлаживать.
У меня вот эти stm32_f105-07_f2_f4_usb-host-device_lib.zip

Выбираю свою версию, собираю, зашиваю и понимаю что устройства в системе нет.
Нужно править все, т.к. эта версия не под discovery, LED я нашел, но сходу смог включить только 2 из 4. И уперся для начала в это. Хотя выставил все параметры для LED одинаковые, кроме номера ножки GPIO (PD12-PD15)
код
#define LEDn                             4
 
#define LED1_PIN                         GPIO_Pin_12
#define LED1_GPIO_PORT                   GPIOD
#define LED1_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
 
#define LED2_PIN                         GPIO_Pin_13
#define LED2_GPIO_PORT                   GPIOD
#define LED2_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
 
#define LED3_PIN                         GPIO_Pin_14
#define LED3_GPIO_PORT                   GPIOD
#define LED3_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
 
#define LED4_PIN                         GPIO_Pin_15
#define LED4_GPIO_PORT                   GPIOD
#define LED4_GPIO_CLK                    RCC_AHB1Periph_GPIOD

Кстати, платка исходно фирмы LC-Tech
www.lctech-inc.com/Hardware/
У них много всего вкусного, но к сожалению китайские (пере-)продавцы
торгуют в основном только их самой дешовой платкой STM32F103C8T6.
Да, к сожалению, есть сложившиеся популярные платы и камни, не всегда самые правильные, но они сильно дешевле всех остальных из-за массовости.
Можно перепаять чип F1xx на более мощный, они совместимы по ножкам :)

Еще мне кажется полезно указать источник софта STSW-STM32121
STM32F10x, STM32L1xx and STM32F3xx USB full speed device library (UM0424)
www.st.com/web/en/catalog/tools/PF258157
Там кстати внутри самая новейшая либа StdPeriph аж версии V3.6.1
Кстати — новое не значит лучше. У меня например с новой версией SPL отказался работать LCD на ILI9xxx серии — FSMC некорректно инициализируется и все тут. Пока не оставил этот модуль от старой библиотеки, экран оставался пустой.
Забавно. Может поменяли формат вызова (добавли/сменили параметры) или может быть ошибка. В любом случае, лучше сделать багрепорт в STM.
Честно говоря понятия не имею куда его направлять. К тому же не факт, что проблема не в LCD контроллере.
У кого-нибудь получалось запустить на STM32F103 USB от внутреннего генератора (HSI)? Интрересует, возможно ли это в принципе, или можно не пытаться, даже на low speed? В datasheet сказано, что для использования USB должен быть включен PLL и HSE, но судя по схеме системы тактирования, PLL может тактироваться также и от HSI, хоть частота и не будет строго 48 МГц. У меня в тестовом проекте PLL судя по коду запускается на частоте ± 48 МГц, но при подключении к компу даже нет виндового звука подключения нового устройства к USB, который, как я понимаю, должен быть сразу после подключения, еще до начала опроса дескрипторов и выбора конфигурации устройства. Вот думаю, проблема ли у меня в прошивке или в самой плате где-то закралась… У кого есть заведомо рабочая плата с STM32F103, отпишитесь, если вдруг получится запустить USB от HSI, или хотя бы получить звук подключения устройства :)
USB — только с кварцем. внутренний генератор не обладает достаточной точностью чтобы поддержать работу по USB — где-то сразу происходит сбой из-за несоответствия скорости и устройство игнорируется.
Я тоже так думал, но в русскоязычном интернете нашел одно упоминание, что якобы у кого-то получилось запустить от внутреннего генератора — тут, поэтому решил уточнить, а то мало ли, может в datasheet-е пишут, что оно не работает, а реально работает, хотя бы на Low Speed, которого мне было бы достаточно. С отсутствием реакции на подключение устройства разобрался — у меня не было подтягивающего резистора, т.к. когда я проектировал плату, то смотрел, к своему сожалению, в основном сюда, а там нету ни резистора, ни упоминания о том, что для USB требуется внешний кварц, поэтому я подумал что в контроллере есть внутренний подтягивающий резистор. Как выяснилось, в некоторых контроллерах STM32 он действительно есть, но не в моем STM32F103.

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

Интересно, что, например, софтверная библиотека V-USB для AVR может работать от 12.8 МГц встроенного RC-генератора, видимо стандарт USB 1.1 не так прихотлив к точности может работать на более низкой частоте…
это называется просто везёт. На некоторых экземплярах будет работать на других нет. Чуть нагрелся и отвалился от ухода частоты… это никуда не годится!

Можно конечно калибровать генератор(есть ли такая функция?) но опять же нужна опорная частота для калибровки, хотябы часовой кварц. Или слушать USB-шину и по импульсам опроса калибровать генератор, а дальше поехали…
Но эти усилия по преодолению проблем которые создаём сами себе не стоят отказа от кварцевого резонатора.
Согласен, что никуда не годится. Таил надежду, что оно может относительно стабильно работать без кварца, т.к. изначально по причине невнимательного чтения документации не предусмотрел его в схеме, и воткнуть кварц в уже разведенную плату, конечно, сложнее :) Теперь, видимо, все-таки придется производить хирургическое вмешательство.
есть плоские кварцы в SMD-исполнении.
По поводу V-USB, там есть спец функция которая калибрует встроенный RC-генератор как раз по USB посылкам от компа.
osccal.c
/* Функция калибрует RC-генератор. Наш опорный источник точного времени -
 *  сигнал SOF, Start Of Frame (один бит SE0), повторяющийся каждую милисекунду
 *  сразу после состояния USB RESET. Мы сначала делаем двоичный поиск величины
 *  OSCCAL, и затем оптимизируем эту величину поиском соседних значений.
 *  Этот алгоритм может также использоваться для калибровки RC-генератора напрямую
 *  до 12 MHz (не вовлекается ФАПЧ, таким образом эту технику можно использовать
 *  почти на ВСЕХ AVR), но это слишком вне спецификации величины OSCCAL и необходимой
 *  точности для тактов на 12 МГц! Используйте RC-генератор, калиброванный на 12 МГц
 *  только для экспериментов!
 */


pastebin.com/7geg5rXU

А потом калибровочные данные сохраняет в еепром, и при загрузки извлекает их из еепрома.
не покатит. рекалибровку надо делать постоянно. Частота плывёт от температуры и напряжения питания(стабилизатор нагревается и напряжение изменяется в процессе работы).
Так она делается по reset'у usb
У нормального стабилизатора параметры не текут =)
Только если вы в -40 подключаете USB девайс, то да за время работы он прогреется =)
А так на моей практике (100+ V-USB устройств на AtTinyX5 без кварца) ни одного проблемного не было.
Были разные девайсы, и которые годами данные снимают к роутеру подключенные, и постоянно перетыкаемые. Все работает в лучшем виде.

osccal.h
/* Имя: osccal.h
 * Автор: Christian Starkjohann
 * Перевод: microsin.ru 
 * Дата создания: 2008-04-10
 * Табуляция: 4
 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
 * Лицензия: GNU GPL v2 (см. License.txt) или проприетарная (CommercialLicense.txt)
 * Ревизия: $Id: osccal.h 553 2008-04-17 19:00:20Z cs $
 */

/*
Основное описание:
Этот модуль содержит функцию, которая калибрует внутренний RC-генератор AVR,
чтобы CPU работал на частоте F_CPU (F_CPU является макропределением, которое 
должно быть задано при компиляции модуля. Лучший выбор - передача этого макро
через командную строку компилятора). Эталон времени - частота фрейма USB 
1 кГц, доступная немедленно после состояния USB RESET. Отсчет времени производится
путем подсчета циклов CPU, при этом все прерывания должны быть запрещены, пока работает
калибровочная функция. Для измерений времени низкого уровня вызывается функция 
usbMeasureFrameLength(). Эта функция должна быть разрешена в usbconfig.h 
путем задания USB_CFG_HAVE_MEASURE_FRAME_LENGTH в 1.

Используемый алгоритм:
calibrateOscillator() сначала делает двоичный поиск в регистре OSCCAL для 
наилучшего совпадения с частотой тактового генератора. Затем она делает поиск
следующей соседней (частоты?) для нахождения наименьшей девиации тактовой 
частоты. Это гарантирует наилучшее соответствие между соседними величинами,
но для генераторов версии 5 (у которых прерывающаяся взаимосвязь между
OSCCAL и частотой) лучшее соответствие может быть доступно в другом диапазоне
OSCCAL.

Ограничения:
Этот алгоритм калибровки может пробовать величины OSCCAL до 192, даже если
оптимальная величина далеко меньше 192. Таким образом, может быть превышена 
допустимая тактовая частота CPU в разработках с низковольтным питанием!
Точность зависит от OSCCAL простив частотной зависимости генератора.
Типичная точность для ATMega168 (вычисленная от OSCCAL против F_RC диаграмма
в даташите) должна быть в диапазоне 0.4%. Только версия 16.5 МГц AVR-USB 
(которая использует ФАПЧ в приемнике данных) может допускать такую девиацию!
Все другие частотные модули требуют точности 0.3%.
*/

#ifndef __OSCCAL_H_INCLUDED__
#define __OSCCAL_H_INCLUDED__

void calibrateOscillator(void);
/* Эта функция калибрует генератор RC, чтобы CPU работал на частоте F_CPU.
 * Она ДОЛЖНА быть вызвана немедленно после окончания состояния USB RESET!
 * Запретите все прерывания во время вызова! Рекомендуется сохранить 
 * результирующую величину в EEPROM так, чтобы хорошее предполагаемое 
 * значение было доступно после следующего сброса.
 */

void    usbEventResetReady(void);

#endif /* __OSCCAL_H_INCLUDED__ */


Вот конкретно мой девайс который как только через *опу не собирали, а он прекрасно работает. =)
Все оказалось проще — у меня подтягивающий резистор был припаян к D-, как предписывает спецификация для Low-Speed устройств. Перепаял резистор на D+, и теперь всё работает, как с внешним кристаллом, так и без него — от внутреннего генератора :)

Извиняюсь за некропостинг. У ST есть некоторое количество чипов, поддерживающих crystal-less режим, они аппаратно калибруют генератор по SOF-пакету. Из тех, что знаю — это серии STM32F0x2 и STM32F0x8.

интересно почему устройство не подключается в линаксе (по виндой работает)

$ dmesg
[ 433.425184] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 435.731027] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 438.037839] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 440.344716] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 454.185890] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 456.492745] hub 4-1:1.0: connect-debounce failed, port 6 disabled
[ 458.799587] hub 4-1:1.0: connect-debounce failed, port 6 disabled
У меня есть вопрос к автору, и боюсь, это совсем глупый вопрос.

Купил именно такую плату. Подключаю к компьютеру, и получаю сообщение Windows, что устройство опознать не удалось, и вероятно, оно работает неправильно. Дискавери тот честно говорит, «я — st-link», а как должен рапортовать этот девайс?

И что, собственно мне, как совсем зелёному новичку в микроконтроллерах, теперь со всем этим делать?
Разумеется. Этот USB не для программирования платы, а штатный вывод USB модуля периферии микроконтроллера.
Вы можете сконфигурировать устройство как вам захочется — эмулировать клавиатуру, мышь, флешку, Custom HID устройство или любое другое. но для этого нужно писать программу.
Пустой МК не будет никак опознаваться, потому что он вообще не отвечает компьютеру на запросы по шине USB, а модуль USB в нем просто выключен.
Уровень зелени новичков бывает сильно разный. Если работали с Arduino и имеете понятие о программировании МК — будет проще. Можно посоветовать CooCox, например, для старта. (В CooCox просто некоторые вещи новичку сделать будет проще, а не потому, что среда хорошая.) А потом выберете себе среду получше на свой вкус. Я использую EmBlocks.
Немного статей по STM32 можно найти у меня на сайте по тегу STM32.
Там есть моргание светодиодом, небольшое описание работы с IDE Emblocks (разных версий), устройство, работающее с USB, прошивка через USART.
Порог входа в STM32 немного выше, чем в AtmegaXX8, но просто потому, что МК намного более нафаршированный, можно настроить практически все на свете, куча полезных фич и режимов, которые я, к примеру, даже наполовину не знаю досконально. Но все их знать и не обязательно. Вполне можно разрабатывать качественные и надежные устройства и обучаться постепенно.
Спасибо за статью!
Скажите, а нет ли ссылки на документацию по библиотеке USB входящей в состав STM32CubeF1?
Дело в том, что там по пути STM32Cube_FW_F1\Middlewares\ST\STM32_USB_Device_Library расположена библиотека, которая судя по сообщению на сайте, заменяет USB-FS. ST нас призывает использовать куб для новых проектов. Для куба есть примеры(мышь я успешно запустил даже), но дело в том, что для USB-FS есть подробное описание UM0424, а для библиотеки входящей в состав куба я ничего подобного не нашел.
Это очень странно конечно, но факт. Может быть кто поможет?
Призывать то призывает и куб вроде неплох, но интегрировать его в простые проекты очень сложно. Он рассчитан на RAD разработку, без оптимизации по размеру кода, нет генератора для Emblocks например, импортировать проект, созданный для keil не получается — очень много ошибок. Документации и опыта по Cube тоже кот наплакал пока. Вот они и пытаются создать сообщество, подталкивая к использованию инструмента.
Но SPL как работала так и работает и вполне подходит.
Немножечко там с оптимизацией проблемы есть, я согласен. Но вполне себе годится. У меня сейчас проектик на stm32f103c8t. usb custom hid, таймеры, ADC, DMA, прерывания, GPIO естественно и конфигурирование тактирования — все с использованием куба. Кода самого куба получилось где-то килобайт 15. Из них около 10 приходится на ЮСБ стек. Так что можно себя нормально чувствовать и на 64кб камнях. Документация есть на все кроме USB почему-то.

Генератора на емблокс может и нет, но есть cube mx, который может сгенерить проект потыкав мышкой.

Я использую gcc, slickedit как редактор и makefile. Немного хардкорно, но все работает:)
А можете показать исходники HIDSTM32.exe?
Пытаюсь заставить код работать на контроллере STM32F103RCT6 (отладочная плата Port103R).
Но получаю только «Сбой запроса дескриптора USB-устройства».
Есть предположения, почему так может быть?
На точно такой же отладочной плате как у автора (тоже с STM32F103C8T6) – такая же ошибка. Попробовал даже делать всё, как автор написал: установил EmBlocks и скомпилировал в точности код из репозитория. Ничего не помогает.
Как задебажить?

Как STM32 USB Device HID устройство может прочитать у PC состояние зелёных светодиодов для USB клавиатуры?

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории