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(uint8_t* Buf, uint32_t* Len) - для приема данных. В данном случае по факту приема данных эта функция будет вызвана "автоматически", а в переменных Buf и Len будут указатель на принятые данные, а также количество принятых байт. Эти данные можно либо сразу обработать внутри CDC_Receive_FS() , либо сохранить для последующей обработки.
  • CDC_Transmit_FS(uint8_t* Buf, uint32_t* Len) - для передачи данных.

Итак, давайте в основном цикле нашей программы будем раз в секунду отправлять 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

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

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

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

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

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

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

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

elis
elis
10 лет назад

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

Roman
Roman
10 лет назад

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

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

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

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

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

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

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

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

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

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

Sergei
Sergei
10 лет назад

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

Pavel
Pavel
10 лет назад

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

Pavel
Pavel
10 лет назад

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

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

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

Pavel
Pavel
10 лет назад

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

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

Keil v5, Dyscovery F407VGT

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

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

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

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

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

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

Pavel
Pavel
10 лет назад

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

niza93
niza93
10 лет назад

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

niza93
niza93
10 лет назад

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

Alex
Alex
10 лет назад

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

Alex
Alex
10 лет назад

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

Alex
Alex
10 лет назад

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

Alex
Alex
10 лет назад

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

Alex
Alex
10 лет назад

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

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

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

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

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

Ivan
Ivan
10 лет назад

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

Max
Max
10 лет назад

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

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

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

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

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

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

Спасибо за статью.
После прошивки МК с диспетчере пояляется 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
10 лет назад

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Boris
10 лет назад

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

Pavel
Pavel
10 лет назад

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

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

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

Efim
Efim
10 лет назад

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Dmitry
10 лет назад

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

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

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

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

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

Dmitry
10 лет назад

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

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

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

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

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

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

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

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

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

Efim
Efim
10 лет назад

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

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

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

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

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

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

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

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

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

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

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

266
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
Обзор конфиденциальности

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