Top.Mail.Ru

STM32 и USB. Реализация USB Virtual COM Port.

Доброго всем дня, сегодняшняя статья будет посвящена реализации виртуального COM-порта для микроконтроллеров STM32. Эта тема уже поднималась на нашем сайте, но, в отличие от всех предыдущих случаев, сегодня мы будем производить все настройки при помощи STM32CubeMx. Собственно, стартуем.

И начинаем с действий, ставших привычными - создаем новый проект в CubeMx. Я буду использовать отладочную плату STM32F4Discovery и, соответственно, выбираю контроллер STM32F407VG при создании проекта.

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

А задача проста - реализуем поддержку USB Virtual Com Port и отправим тестовый набор данных с платы на ПК. Таким образом, мы должны добиться определения нашей отладочной платы в системе как виртуального COM-порта. А открыв этот порт в какой-нибудь терминальной программе мы должны будем увидеть правильно принятые данные. Просто и наглядно, приступаем к осуществлению.

Первым делом включим поддержку USB в проекте. Для этого посещаем вкладку "Pinout & Configuration":

USB device

Кроме того, задействуем внешний тактовый генератор (8 МГц), установленный на плате - ровно так же как мы делали в статье про тактирование:

HSE в STM32CubeMx

Осталось выбрать режим работы USB для нашего устройства:

USB CDC class

На этом первый этап настроек проекта закончен, переходим в окно настроек тактирования (вкладка "Clock Configuration"). Здесь нам необходимо обеспечить подачу ровно 48 Мгц для тактирования модуля USB, привожу полную схему с выставленными значениями:

Тактирование USB в STM32CubeMx

Среди многочисленных настроек USB давайте поменяем только PRODUCT_STRING, исключительно теста ради, проверим, как это сработает. Остальное пока не трогаем:

Настройки дескриптора.

В принципе, на этом все, можно смело переходить к генерации проекта и исходного кода...

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

Виртуальный COM-порт в Windows.

Если мы зайдем в свойства, то можем увидеть там значения VID и PID, которые были установлены в настройках STM32CubeMx, а кроме того измененную нами строку PRODUCT_STRING:

USB Virtual COM Port на плате STM32F4Discovery.

Никаких сомнений в правильной работе сгенерированного проекта не остается 👍 Но это только часть задачи, нужно реализовать отправку данных. А необходимые для этого функции находятся в файле usbd_cdc_if.c:

  • CDC_Receive_FS() - для приема данных.
  • CDC_Transmit_FS() - для передачи данных.

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

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
  
  uint8_t testDataToSend[8];
  for (uint8_t i = 0; i < 8; i++)
  {
    testDataToSend[i] = i;
  }

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_Delay(1000);
    CDC_Transmit_FS(testDataToSend, 8);
  }
  /* USER CODE END 3 */
}

Не забываем также добавить в начале файла директиву #include:

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"

/* USER CODE END Includes */

Теперь остается только прошить контроллер, открыть терминал и убедиться, что данные принимаются верно. Так и делаем:

Реализация приема данных

Все работает отлично, как и планировалось. Собственно, на этой мажорной ноте мы заканчиваем сегодняшнюю статью, а вместе с ней и обсуждение реализации USB Virtual COM Port при помощи STM32CubeMx. В следующих статьях мы будем работать уже с другими режимами USB, так что оставайтесь на связи 🤝

Подписаться
Уведомить о
guest

264 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Ali
Ali
9 лет назад

Здравствуйте, каким вы терминалом пользуетесь?

vladk
vladk
Ответ на комментарий  Aveal
7 лет назад

Попробовал эту программу - очень даже да, но!
Не смог найти где выбирать эмулируемый терминал - хотя бы VT102.

"терминал" без эмуляции терминалов - деньги на ветер.

RusikOk
RusikOk
Ответ на комментарий  vladk
2 лет назад

скачай бесплатно)

elis
elis
9 лет назад

Спасибо за статью)

Roman
Roman
9 лет назад

Ну что за непруха. Опять (SD так и не заработала) не получается "USB составное устройство" с ошибкой. А могут мои проблемы быть связаны с особенностями компиляции работы ЮСБ и СД в Кейле 5? ктоньть пробовал на кейле?

віталік
віталік
9 лет назад

в мене після кількох рестартів мк запускався нормальний драйвер, а не композіт девайс

віталік
віталік
9 лет назад

щоб проект запрацював, треба у функції CDC_Transmit_FS змінну UserTxBufferFS змінити на Buf і плюс до того, якщо 64б віндовс, то у стартапі проекту змінити Stack_Size EQU 0x00004000 та Heap_Size EQU 0x00002000. А так все працює. Дякую.

stscat
stscat
Ответ на комментарий  віталік
8 лет назад

Точно. Так и надо сделать. На 64 разрядной винде все заработало. Проект генерил в Keil 4.74

stscat
stscat
Ответ на комментарий  stscat
8 лет назад

И еще в main.c добавить:
#include "usbd_cdc_if.h"

тогда не будет предупреждения
warning: #223-D: function «CDC_Transmit_FS» declared implicitly

Sergei
Sergei
9 лет назад

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

Pavel
Pavel
9 лет назад

Доброго времени суток! Спасибо за статью, очень полезно и интересно. Но есть у меня с данным примером проблема: отказ виртуального СОМ порта. Что я делаю не так, с чем это связано? Заранее спасибо!

Pavel
Pavel
9 лет назад

Я вот пробую. Не работает. Но дело не в кейле.

Сергей
Сергей
9 лет назад

всем здравствуйте. Нужна помощь с генерировал по статье код для MDK-ARM v5 stm32l152 выдает предупреждение
..\Src\main.c(97): warning: #223-D: function "CDC_Transmit_FS" declared implicitly
и зависает при отправке. кто сталкивался с такой проблемой уже второй день борюсь помогите пожалуйста

Pavel
Pavel
9 лет назад

Порт появляется в диспетчере, но он не работает. В свойствах указано: не удается запустить устройство (код 10). И при попытке обращение к этому порту, выдает ошибку, что такого порта нет.

Pavel
Pavel
Ответ на комментарий  Aveal
8 лет назад

Keil v5, Dyscovery F407VGT

Alex Sh
Alex Sh
Ответ на комментарий  Pavel
8 лет назад

В файле startup_stm32f407xx.s поменяй Stack_Size на 4000 вместо 400 и Heap_Size на 2000 вместо 200. Проблема исчезнет.

Адилет
Адилет
Ответ на комментарий  Alex Sh
7 лет назад

Спасибо, хороший человек, ошибка исчезла

Игорь
Игорь
Ответ на комментарий  Alex Sh
4 лет назад

А где именно и что именно использует так много места?
Что если я хочу принимать, например, 1 Мб данных?
Они точно не влезут все в кучу.
у меня есть внешняя SDRAM, она прекрасно работате и я хочу часть ее памяти зарезервировать под обработку USB пакетов, Но что-то никак не могу найти где же это используется..
Причем нигде толком не нашел объяснения.
Все только и пишут, что нужно объем стека и кучи увеличить..

Pavel
Pavel
9 лет назад

STM32F4-DISCOVERY c 407 контроллером. KEIL v5 и KEIL v4 пробовал.

niza93
niza93
9 лет назад

Был трабл с зависанием, теперь решился, благодаря
уроку отсюда
http://www.youtube.com/watch?v=enZqu2FV1eU
мб, кому-то поможет
работал на F103
но теперь другой трабл, при подкл./откл. от ПК никаких проблем нет, однако если во время подключения к ПК принять через ком порт данные и, закрыв соединение, отключить провод, то иногда при повторном подключении устройство улетает в HARDFAULT_handler из функции USBD_CDC_DeInit через функцию USBD_free(pdev->pClassData);
может, кто то сталкивался???

niza93
niza93
9 лет назад

сам решил проблему:
в файле usbd_conf надо закоментить 494 строку
//free(p); проблема сразу решилась и без плясок с бубном как на видео

Alex
Alex
9 лет назад

Большое СПАСИБО за статью. Есть проблема, драйвера ни в какую работать не хотят устройство видеться. Код ошибки 10. Если в CUBE поменять параметр USBD_MAX_NUM_CONFIGURATION на отличный от 1 код ошибки исчезает, однако данные через виртуальный ком порт не идут. При попытки отправить данные в ком порт есть ошибка превышения таймаута. Если можно по подробнее на счет настроек по точнее. Какие параметры выставить в cubemx чтобы виртуальный ком порт прочухался. Спасибо

Alex
Alex
9 лет назад

В качестве среды разработки используется for IAR Embedded Workbench for ARM version 7.40.2 попробовал с платами stm32f4discovery и stm32f429 discovery эффект один и тот же

Alex
Alex
9 лет назад

драйвера с сайта st пробовал под win_xp 32 Win 7 32 однотипно как в первом посте .... Подскажите куда копать ... а то смотришь красиво начинаешь ковырять и вот...((((((((

Alex
Alex
9 лет назад

Спасибо за ссылки посмотрел повертел и результат никакой ((( ... есть подозрение что с Н-ной версии CUBE MX стал страдать "прихрамыванием"...(

Alex
Alex
9 лет назад

Вопрос с драйвером решился для iar следующим образом : в настройках IAR увеличение размера "кучи" и стека

Альфис
Альфис
9 лет назад

Что за переменная lt в форе "for (uint8_t i = 0; i < 8; i++)"

Альфис
Альфис
9 лет назад

А видимо глюк в коде на сайте!

Ivan
Ivan
9 лет назад

У меня проблема решилась уменьшение максимального размера пакета с
512 до 64
#define CDC_DATA_HS_MAX_PACKET_SIZE 64

Max
Max
9 лет назад

Нужно поставить Heap_Size EQU 0×00004000 и будет счастье

Сергей
Сергей
9 лет назад

Отично! Все работает! Спасибо!

Паша
Паша
9 лет назад

Будет пример реализации в качестве Host-a?

Алексей
Алексей
9 лет назад

Спасибо за статью.
После прошивки МК с диспетчере пояляется Unknown Device. Ставил драйвера VCP_V1.3.1_Setup_x64. (http://www.st.com/web/en/catalog/tools/PF257938).
Подскажите где капать решение проблемы. И еще вопрос. Мне надо организовать мост USB - USART. Использую HAL драйвера и STM32_USB-FS-Device_Lib_V4.0.0. Может быть есть какой нить пример решения.

Алексей
Алексей
Ответ на комментарий  Aveal
9 лет назад

Я извиняюсь. Прочитал многие Ваши статьи (спасибо за ваш труд), а ответ написал не в той)))
После генерации в кубе все работает, порт определяется, данные посылаются. Пробовал ваш проект из статьи Микроконтроллер STM32 и USB(https://microtechnics.ru/mikrokontroller-stm32-i-usb/). вот с этим проектом - неизвестное устройство. Хотел поэкспериментировать.... и никак. А по поводу моста - принцип понимаю, но есть вопросы. Если не ошибаюсь эти обработки надо писать в прерывании в файле stm32f3xx_it.c. Запутало то, что не могу понять где и как организовываются endPoint . Немного о проекте: по USB мне надо конфигурировать мое устройство (менять некоторые параметры). К устройству через usart подключен радио модем которые передает сигнал исполнительному устройству. Так вот через мост usb-usart надо настраивать модем( частоты , канал и тд.) В общем пока, что каша в голове, так как только вчера начал разбираться с USB. Ищу примеры что бы разобраться.

Алексей
Алексей
9 лет назад

После генерации в кубе система определяет STMicroelectrinics Virtual COM Port. Хочу , что бы определялось типа Мое устройство(COM10). Меняю VID PID и соответственно устройство не определяется. Как можно написать свои драйвера для своего устройства. Может есть какая нить инструкция.

Владимир Березин
Владимир Березин
9 лет назад

У меня на старенькой Windows XP такая же проблема. vcp-драйвер версии 1.4.0 от STMicroelectronix не помог.

Николай
Николай
8 лет назад

Спасибо автору за статью. Удалось разобраться с настройкой USB CDC. У меня осталось несколько неясных моментов. Особенно интересует как убедиться в готовности USB, прежде чем отправлять через него данные. У меня устройство работает автономно, передавая по USB данные измерений. Но подключено к компьютеру оно не всегда, периодически отключается. Так вот как мне в программе определить подключен ли USB или нет. Устройство перезапускать нельзя. Заранее спасибо 🙂

Николай
Николай
8 лет назад

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

Павел
Павел
8 лет назад

Помогите! Может у кого было...? После сборки и загрузки проекта в KEILe подключаю USB, а определяется как 2 COM порта!? Это как? Я новичок прошу сильно не пинать!

Дмитрий
Дмитрий
8 лет назад

Спасибо за статью, всё заработало.

Но пока так и не нашёл, где менять настройки порта.
По умолчанию стоит 9600, и где менять - непонятно.
Смотрел Line_Coding, но там мало материала.

Boris
8 лет назад

Если настроить тактирование как у автора проблем не должно быть .Это я об ошибке 10(помогает CDC_DATA_HS_MAX_PACKET_SIZE 256). Следующая ошибка 28 относится к установке драйверов.Проблема в том что никто не читает инструкцию по установке драйвера .Одним запуском еxe из архива дело не обходится он драйвера не устанавливает , а распаковывает в STMicroelectronics/...читаем файл readme.txt и делаем все как написано.

Pavel
Pavel
8 лет назад

У меня как-раз таки виртуальный ком-порт не появляется в системе

Ефим
Ефим
8 лет назад

контроллер STM32F103C8T6 в системе определяется как ункновн девайс может кто подскажет, кто сталкивался (тестером кабель и от МК до порта все проверил) МК не выдает VIP и PID в чем проблема 🙁

Efim
Efim
8 лет назад

Ув. Aveal настройки дефоултовые от кварца на 8М, частота на USB 48M куда еще смотреть?

Ефим
Ефим
8 лет назад

Ув. Aveal от внутреннего не хочет, куб ругается

Ефим
Ефим
8 лет назад

Ув. Aveal у меня контроллер STM32F103C8T6 кварц на 8Мгц в RCC ставлю внешний кварц, автоматом частота 48 Мгц, но могу и 72 (максимальная) поставить (могу скрины кинуть ), а от внутреннего пишет USB работать не будет

Ефим
Ефим
8 лет назад

Ув. Aveal готовая отладочная маде ин наши ускоглазые соседи https://detail.tmall.com/item.htm?spm=a230r.1.14.97.d3erSV&id=522586249180&ns=1&abbucket=9

Ефим
Ефим
8 лет назад

1. на счет тактирования куб сам ставит, что надо
2. так хоть бы vip и PID было видно, а то просто ункновн
3. есть такой вариант, т.к. я так понимаю еще правят в нем ошибки
а может просто где галки не хватает

Ефим
Ефим
8 лет назад

Ув. Aveal
вот схема тактирования, которая сейчас с USB
http://s019.radikal.ru/i604/1603/d8/a200093d101b.jpg

с таймером брал значение частоты на APB1 Timer Cloсks там было 36, но результат был как будто значение было другим

Ефим
Ефим
8 лет назад

Прихожу к выводу, что куб генерирует некорректный код. проделал опыт с таймером и указал частоту 8МГц и значения 8000 и 499 соответственно, все ок. Потом добавил USB настройки частот как на фото выше, т.е. на таймере должно быть 48МГц, выставляю значения 48000 и 499 и получаю 6 секунд.
при частоте 72Мгц поставил 36000 и 499 и так же 6 секунд. хотя должно быть 2. В общем или я что не понимаю, или куб врет

Dmitry
8 лет назад

Добрый вечер. Попала в руки плата STM32F429I-DISCO. Решил освоить периферию и наконец перейти на STM32CubeMX(Так сказать убить двух зайцев сразу). Но вот незадача, решил начать с USB (VIrtual Com Port). Настраиваю USB_OTG_FS, RCC, USB Device как Virtual com port. Генерю код и ничего не изменяю загружаю прошивку. Просто хочу проверить связь с устройством, но не тут то было. Комп отказывается искать устройство вообще! То есть не всплывает даже "Неопознанное устройство". Вообще 0 эффекта. Не могу понять, что за грабли на которые я наткнулся.

Dmitry
Ответ на комментарий  Aveal
8 лет назад

Настройка PinOut
Настройка Clock (на всякий случай)
https://dropmefiles.com/qg3VM

Ефим
Ефим
8 лет назад

Ув. Aveal отправил вам на почту с контактов в архиве проект для воркбенха и репорт из куба

Dmitry
8 лет назад

Странно. И правда пины РВ13, РВ14 и РВ15. А куб генерит под другие для этого микроконтроллера.

Dmitry
Ответ на комментарий  Aveal
8 лет назад

А можно как нибудь в кубе изменить пины?или только самому в коде?

Dmitry
Ответ на комментарий  Aveal
8 лет назад

Не помогло(((

Dmitry
Ответ на комментарий  Aveal
8 лет назад

https://dropmefiles.com/JRbsK
Вот...кубовский

Dmitry
Ответ на комментарий  Aveal
8 лет назад

Большое спасибо)Наконец то плата определилась)

Efim
Efim
8 лет назад

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

Ефим
Ефим
8 лет назад

от внутреннего кварца таймер работает хорошо , USB проверить не могу, т.к. не позволяет, а вот только как вместо встроенного кварца выбираешь внешний, частота увеличивается (точнее снижается) в 6 раз. вместо герца 1 в 6 секунд

Ефим
Ефим
8 лет назад

http://s020.radikal.ru/i703/1603/2c/9e1b673b270e.jpg ругается в системе тактирования

Ефим
Ефим
8 лет назад

Ув. Aveal замена кварца решила проблему 🙂 (ремонт обошелся в 36р) первый раз с таким сталкиваюсь, а так значит делал все правильно

Ефим
Ефим
8 лет назад

Если честно заказывал очень много чего, за все время, только второй раз вылез косяк, но тут чисто брак кварца (это как брак процессора 1-2 на 1000 штук), а так спасибо за помощь

Павел
Павел
8 лет назад

Как понять подключен хост (ПК) или нет?
У меня если шнурок выдернут то при попытке CDC_Transmit_FS контроллер уходит HardDefault. В usbd_cdc_if.h и usbd_cdc_if.с ничего подобного не увидел.
Хотелось бы понять, когда делать CDC_Transmit_FS а когда нет.

264
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x