Usb vcp что это

Обновлено: 06.07.2024

Для изучения работы USB в микроконтроллерах STM32F105, STM32F107 существует определенное количество отладочных плат. Большинство из них имеет высокую стоимость, но, при этом, существуют демо-проекты, написанные и отлаженные производителем STMicroelectronics, которые без дополнительных усилий можно сразу загрузить в эти платы и все будет работать.

Существуют и дешевые отладочные платы, например STM32-H107 фирмы Olimex. Но проблема в том, что для дешевых плат нельзя найти готовые для использования демо-проекты.

Эта статья представляет демо-проект виртуального COM порта, который содержится в библиотеке от STMicroelectronics stm32_f105-07_f2_f4_usb-host-device_lib\ STM32_USB-Host-Device_Lib_V2.1.0\Project\USB_Device_Examples\VCP\TrueSTUDIO\STM3210C-EVAL_USBD-FS , адаптированный для работы с отладочной платой STM32-H107 и результаты тестов скорости передачи.

Распакуйте архив проекта. Запустите Atollic TrueStudio.

Выберите File->Import->General->Existing Projects into workSpace->Next.

Выберите папку проекта VCP.

Установите галку Copy projects into workspace.

Скомпилируйте проект и он готов к загрузке в плату STM32-H107.

При создании проекта установлена конфигурация JTAG порта процессора как ST-Link.

Я использовал ST-Link, имеющийся на отладочной плате STM32VLDISCOVERY. См. рисунок ниже.

5.jpg

Схема соединений следующая:

Предварительно, на персональном компьютере (PC) надо установить драйвер от STMicroelectronics VCP_V1.3.1_Setup.exe.

Загрузите исполняемый код в STM32-H107 и запустите его выполнение.

Через небольшое время, необходимое для инициализации виртуального COM порта, на PC в диспетчере оборудования, в разделе порты COM и LPT появится устройство виртуальный COM порт, как показано на рисунке ниже.


Номер порта назначается первый свободный в системе.

Если этот номер не устраивает, его можно изменить средствами операционной системы ОС.

В этой статье не рассматривается использование виртуального COM порта по его прямому назначению, когда данные, принятые от РС через USB, отправляются на передачу через USARTx (UARTx) микропроцессоров STM32F105 или STM32F107, а данные, принятые USARTx(UARTx), отправляются на передачу через USB микропроцессоров на РС. Это требуется только в случае построения USB-serial преобразователей.

Гораздо более интересное использование этого демо-проекта для обмена по USB в режиме CDC (common device class).

В классическом варианте использования CDC должна быть библиотека функций для использования в программе микроконтроллера STM32F10x (это

библиотека STM32_USB-Host-Device_Lib_V2.1.0 и она свободно распространяется на сайте STMicroelectronics).

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

Обойти вопрос покупки библиотек можно, используя со стороны микроконтроллера режим передачи CDC, а со стороны РС только драйвер виртуального COM порта. Все необходимые функции для работы с виртуальным COM портом такие же, как для обычных СОМ портов и содержатся в WinSDK. Функции объявлены в файле winbase.h, а содержатся в библиотеке kernel32.lib.

Эти функции следующие:

При помощи этой функции открывается СОМ порт.

Ниже дается пример вызова функции:

При помощи этой функции закрывается СОМ порт.

BOOL CloseHandle(HANDLE hObject); // handle to object to close

Функция для передачи данных от PC на COM порт:

Данные от СОМ порта принимаются в отдельном потоке при помощи:

Для того, чтобы на стороне микроконтроллера использовать режим CDC, в библиотечный файл usbd_cdc_vcp.c добавлена функция

uint16_t CDC_DataTx (uint8_t* Buf, uint32_t Len); , которая является аналогом имеющейся там функции uint16_t VCP_DataTx (uint8_t* Buf, uint32_t Len);

, с разницей в источнике данных для передачи. Для первой функции это uint8_t* Buf - массив данных, который требуется передать, второй функции данные поставляет USARTx(UARTx) микроконтроллера.

Таким образом, функция CDC_DataTx является точкой входа для передачи данных по USB от микроконтроллера на РС.

На стороне PC использовалась самодельная программа для приема/передачи байтов по порту RS232, окно которой показано ниже:

1.jpg


Рис.1

Она позволяет:
- оперативно открывать/закрывать COM порт с любым номером
- устанавливать требуемую скорость работы порта
- имеет поток, который принимает байты от порта и выводит их на левый экран.

Для случая проверки максимальной скорости передачи, вывод принятых байтов на экран заблокирован, а добавлен счетчик, который выводит на форму количество принятых байтов в секунду(обведено красным).

- передавать из правого окна одиночные байты, массивы байтов и строки.

Для проверки максимальной скорости передачи от микроконтроллера к PC, на плате STM32-H107 надо нажать кнопку WKUP. Загорается зеленый светодиод, микроконтроллер в цикле main следит за переменной USB_Tx_State. Когда она становится равной 0(т.е.ресурсы USB на передачу свободны), загружает эти ресурсы очередным массивом данных.

Из рис.1 видно, что скорость передачи составила 424.5 килобайт/сек. Такая скорость получена при установке в 0 параметра

В этой проверке установленная скорость виртуального порта не играет никакой роли.

Прием байтов от РС

Из программы на РС передается байт 123 (см.рис.2)

4.jpg


Рис.2

На рис.3 видно, в каком месте проекта появляется принятый от РС пакет.

3.jpg


Рис.3

Принятый от РС пакет содержит переданный байт 123(фигурная скобка), USB_Rx_Cnt=1, т.е длина пакета равна 1.

Для проверки максимальной скорости передачи байтов от PC на микроконтроллер программа на РС передавала пакет из 64 байтов и ждала подтверждения от микроконтроллера о приеме пакета. Потом цикл повторялся. Функция usbd_cdc_DataOut в программе микроконтроллера была модифицирована следующим образом:

7.jpg

Т.е функция APP_FOPS.pIf_DataRx(USB_Rx_Buffer, USB_Rx_Cnt); закомментирована, чтобы она не передавала принятые байты в USART микроконтроллера. Поток, работающий на прием на РС, подсчитывал, при этом, 1-байтовые ответы от микроконтроллера.

На рис.4 показан результат теста:

6.jpg


Рис.4

Скорость передачи составила 8926 х 64 = 571264 байт/с.

Следует отметить, что и в этом тесте установленная скорость виртуального порта не имеет никакого значения. Можно поставить малую скорость, например 115200 бит/с, а результат остается тем же.


Раз у камня есть аппаратный USB, то грех им не пользоваться. Один из способов плюнуть байтом в компьютер и чтобы он при этом не очень обиделся — это организация виртуального COM-порта.
Все в железе пробовалось на камне STM32F103ZE, на аналогах тоже должно взлететь.

Забиваем.

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

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

Не забываем дрова виртуального ком-порта. У меня вообще-то оно само все нашлось, но я много чего ставил от STM, может там в комплекте и пришлись.

Также нам пригодятся следующие стандарты
USB 2.0 Specification
USB CDC

В составе библиотеки есть пример как раз организации виртуального COM-порта. Правда там он сделан как мост USART-USB, но мы же не боимся трудностей?


Цель этой статьи — разобрать приложение, делающее следующее:

Поджигаем


Собираем проект из нужных нам библиотек: CMSIS, SPD, USB. Дерево проекта прилагаю.

Как обычно, самое интересное в папочке /src. Вот её-то и будем разбирать.

Неторопливо курим

Начнем с раскуривания библиотеки от STM


Эта библиотека предназначена и для connectivity-line устройств (это STM32F105/107), у них не просто USB FS, а USB OTG. Поскольку камней с OTG у меня пока нет, сконцентрируемся на простом USB FS.
В примере, который мы взяли за основу, есть куча дефайнов, как раз на случай отличить connectivity-line от других демоплат. Я эти дефайны повырезал, чтобы глаза не мозолили.

Cо всей картинки нас интересует High Layer — синенькие квадратики, которые и составляют, собственно, пользовательскую часть библиотеки. Их мы меняем под свои нужды, все остальное остается неизменным. Если заглянуть в папочку /src, то видно, что все эти файлики там и собраны.

Первая затяжка — usb_conf.h

Самые общие настройки библиотеки.
Указано сколько у нас будет endpoints (а нам их надо 4 штуки — нулевой для начального конфигурирования устройства, один для команд, один для приема и один для передачи).
Также расписаны, какие нам будут нужны коллбэки. Все взаимодействие библиотеки и пользовательской программы построено на обратных вызовах: в случае возникновения какого-либо события вызывается функция с заданным названием. А уже содержание этой функции — проблема разработчика.
Нам будет нужен SOF_CALLBACK – сигнал начала фрейма (Start Of Frame). По нему будем выплевывать то, что накопилось в буфере передачи.
Также резервируем еще два коллбэка — на прием и передачу. По приему символа будем мигать светодиодами, чтобы уж как-нибудь задействовать канал приема.

Упс, кончился файл. Короткая получилась затяжка.

Файл берем из примера, ничего не меняем.

Вторая затяжка — usb_desc.h / usb_desc.c

В этих файлах находятся дескрипторы устройства и эндпоинтов.
Информация по стандартным дескрипторам есть в стандарте USB, в разделе 9.6 Standard USB Descriptor Definitions
Специфические дескрипторы описаны в USB CDC, раздел 5 (так и называется Descriptors),

Эти все тонны текста в стандартах для того, чтобы USB стала действительно Universal. Поэтому тщательно выведена классификация устройств и интерфейсов — чтобы глянув на дескриптор хост сразу понял, что с этим делать.

Особо подробно разбирать смысла не вижу — это не характерно для STM32, это общая боль разработчиков USB устройств.

Файл берем из примеров, ничего не меняем.

Продолжение дескрипторов — usb_prop.h / usb_prop.c

В этих файлах описана таблица реакции на запросы. Все запросы к устройству пронумерованы и стандартизованы. В этих файлах определяется массивы функций Device_Property, User_Standard_Requests и просто массивы String_Descriptor, например. Это все используется ядром. Когда в устройство приходит определенный запрос, например «Выдай мне дескриптор устройства», то ядро посмотрит в таблице, какая функция обрабатывает этот запрос, вызовет эту функцию, а оно уже отработает:


Опять же, берем файл из примеров.

Прерываемся — usb_istr.h / usb_istr.c

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

Прерывание будет настраиваться в файле hw_config.c, обработчик выглядит очень просто:

void USB_LP_CAN1_RX0_IRQHandler(void)
USB_Istr();
>

его можно разместить в файлах stm32f10x_it.*, а в данном проекте, чтобы не растекаться мысью по древу, я его включил в файл main.c

И тут особо ничего не меняем, все как в примере.

Питание — usb_pwr.h / usb_pwr.c

Здесь все, что касается питания. По стандарту, устройство может быть переведено в режим спячки, тогда, если оно питается от порта, нужно позаботиться об отключении жрущей периферии. Поскольку у нас плата питается отдельно, то особого смысла в управлении питанием нет. Просто устройство формально переводится в состояние SUSPENDED.

Ничего не меняем, файл из примеров.

Коллбэки — usb_endp.c

Этот файл я переписал, поскольку у нас не будет работы с USART, как это было в примере. Приведу код с комментариями:

Работа с железом — hw_config.h / hw_config.c

В этом файле собраны функции инициализации периферии, прерываний, функции управления светодиодами и работы с буфером отправки.


USB-порт и подтяжки на моей плате сделаны по такой схеме:

И USB_EN заведен на пин PF11. Значит надо не забыть его проинициализировать и дернуть вовремя.

По сравнению с примером, выкинуты функции инициализации и работы с USART, добавлена функция мигания светодиодом.

По приему символов 'A', 'B', 'C', 'D' – зажигаются соответствующие светодиоды, 'a', 'b', 'c', 'd' – гасятся.
'1' и '0' — соответственно зажигают и гасят все светодиоды.

Ну и все, что будет передано функции USB_Send_Data() попадает в буфер, а затем и через USB – в комп.

Уфф. С USB вроде закончили.

Теперь в головной программе можно просто вызывать USB_Send_Data() и посимвольно передавать данные в комп.

Если мы на этом остановимся, то размер кода будет порядка 11 кБ:


Более двух килобайт bss – это буферы приема и передачи. Понятное дело, их можно уменьшить.

Выдыхаем — printf()

Но мы же хотим, чтобы вывод функции printf() перенаправлялся в наш свежесозданный COM-порт. Подключаем <stdio.h> и офигеваем от количества ошибок линковки:

А тут все просто — стандартная библиотека ввода-вывода подразумевает работу с файлами, но в больших системах есть ОС, которая собственно и занимается организацией файлов для программ пользователя. А поскольку у нас нет никакой ОС, то библиотека вполне справедливо недоумевает «А что же мне делать-то?»

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

Видим, что как раз и вызывается наша функция USB_Send_Data()

Все, компилим, собираем, запускаем.

Архив с проектом прилагаю — это на случай, если кто не заметит маленькие буковки внизу :)

Всем привет! Сегодня будем поднимать USB CDC (VCP) на плате stm32f401c-disco.

USB communications device class (коммуникационный класс устройства) — является составным классом устройства Универсальной последовательной шины. Класс может включать один (или более) интерфейс, такой как интерфейс пользовательского элемента управления, интерфейс передачи данных, аудио или интерфейс запоминающего устройства.

Базовый класс 02h (Communications and CDC Control)
Этот базовый класс определен для устройств, которые относятся к классу устройств спецификации связи. Эта спецификация определяет используемый набор подкласса и Протокола значений. Значения за пределами определения спецификации защищены. Обратите внимание, что связи класса устройств спецификации требуется несколько значений Кода класса (три), которые будут использоваться в описания устройств, а некоторые, которые будут использоваться в интерфейсе дескрипторов.

Базовый класс 02h
Подкласс xxh
протокол xxh
смысл Communication device class

Базовый класс 0Ah (CDC-Data)
Этот базовый класс определен для устройств, которые относятся к классу устройств спецификации связи. Это спецификация определяет используемый набор подкласса и протокола значений. Значения за пределами определения спецификации защищены. Эти коды класса могут быть использованы только в интерфейсе дескрипторов.

Базовый класс 0Ah
Подкласс xxh
протокол xxh
смысл CDC data device




4. Теперь нужно добавить в usbd_cdc_if.h несколько строк кода

5. Устраняем баг для USBD_CDC_TransmitPacket()

6. И добавляем пример в main.c


И все готова!, подключаем микро USB к плате, второй вывод к host-у и у нас появляется виртуальный com порт.

6 thoughts on “ Старт ARM. Поднимаем USB CDC. ”

I corrected it with:

if (size > CDC_DATA_HS_OUT_PACKET_SIZE) int offset;
for (offset = 0; offset < size; offset += CDC_DATA_HS_OUT_PACKET_SIZE) int todo = MIN(CDC_DATA_HS_OUT_PACKET_SIZE, size - offset);
int done = VCP_write(((char *) pBuffer) + offset, todo);
if (done != todo)
return offset + done;
>

with large data is not working, thanks

Точно, спасибо за инфу.

Есть одна проблема. Не передаются пакеты более 64 байт. Кто-нибудь решил ее?


USB VCP stm32f303vc
Всем привет. Избавился в проекте от UART-USB драйвера посредством аппаратного USB с эмуляцией ком.

USB VCP на STM32
Был реализован режим эха: всё, приходящее в порт, немедленно отправляется обратно. В файл.

STM32F407VET6 USB VCP
Привет. Столкнулся с проблемой USB VCP на STM32F407VET6. Подняли USB VCP (и всю остальную.

STM32f4 + USB (VCP) +DMA
Прикручен пример из стандартной библиотеки stm32_f105-07_f2_f4_usb-host-divice_lib. У меня на.

Frater, данные толкаете в USB прямо в прерывании? Нет, прерывание вызывает функцию, а уже в этой функции отправляю данные Судя по тому, что "пришел специальная команда от пк, тогда все отлично отсылается", ошибка видимо в том, как вы данные "отправляете". Вы спецификацию USB читали? В каком режиме работает ваше устройство? Устройство не может само инициировать обмен с хостом. Нет, прерывание вызывает функцию, а уже в этой функции отправляю данные

Так это же то же самое что и из прерывания отправлять.

Попробуйте выставить флаг, а в бесконечном цикле отправлять, не из прерывания

Добавлено через 2 минуты

Так это же то же самое что и из прерывания отправлять.

Попробуйте выставить флаг, а в бесконечном цикле отправлять, не из прерывания

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

smr32f103 usb VCP не поднимается
Ребята, помогите пожалуйста, 2 дня без сна (( Взялся изучать smt32. Намигался диодами, попробовал.

stm32f2 usb cdc (vcp)
Не получается запустить usb на stm32f2. Пробовал генерировать проект в stm32cube. При подключении.

STM32F105 Cube USB VCP Unknown device
День добрый! Была платка с STM32F103, посадил на нее STM32F105 камень. Разведены только линии DP.

Драйвер (не VCP) для встроенного USB STM32
Всем привет ! На сайте STM нашел только VCP драйвер ( STSW-STM32102 STM32 Virtual COM Port Dryver.

STM32F4 USB VCP проблема TimeOut-а при передачи данных от PC
Здравствуйте. Использую пример VCP (Virtual COM Port) от ST. Работаю под WinXP с виртуальным COM.

STM32L1xx и USB (VCP): все работает, но ничего не работает.
Запускаю пример для USB VCP (причем, даже собранный под камень L151, хотя у меня Dyscovery с L152 .

Читайте также: