Usb cdc stm32 зависает

Обновлено: 04.07.2024

Всем привет! Сегодня будем поднимать 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 байт. Кто-нибудь решил ее?


Часовой пояс: UTC + 3 часа

STM32F103, HAL + USB-CDC - у кого работает нормально?

Сгенерил кубом проект, начал ковырять - наткнулся на несколько непоняток:
1. При передергивании юсб - вешается (скорее всего вываливается где-то в эксепшн).
2. Медленная инициализация (на глаз - десятые доли секунды, а то и до секунды). Затык на установке клока. Из-за чего не всегда юсб подхватывается.
3. При нажатии ресета с подключенным юсб - компу ничего не отправляется, в итоге комп считает, что девайс инициализирован и рабоатет, девайс видимо считает иначе, итог - cdc устройство живет, но на отправляемые данные не реагирует. Лапа юсб подтянута на плате резюком на плюс не через ключ, потому сымитировать реконнект не выйдет.

Собссно вопросы - кто-то с таким сталкивался? Если да - как решали?

кинь проект, попробую залить себе.

JLCPCB, всего $2 за прототип печатной платы! Цвет - любой!

Проект - обычная сгенеренная кубом заготовка.

По п.2 - виноват был RTC кварц. Почему-то долго RTC в режим входит(около секунды). На всех нескольки платах, что есть в наличии. Похоже - defective by design. Пока отключил его нафиг.

По п.3 - похоже, нужно таки отдельный транзистор.

А вот п.1 - явная бага библиотеки.

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

К слову, в Leaf mini подтягивающий резистор, ну который сообщает юсб хосту что воткнут девайс, похоже, заведен правильно, через ключ.

Приглашаем всех желающих 25/11/2021 г. принять участие в вебинаре, посвященном антеннам Molex. Готовые к использованию антенны Molex являются компактными, высокопроизводительными и доступны в различных форм-факторах для всех стандартных антенных протоколов и частот. На вебинаре будет проведен обзор готовых решений и перспектив развития продуктовой линейки. Разработчики смогут получить рекомендации по выбору антенны, работе с документацией и поддержкой, заказу образцов.

С аналогичной платой проблема! Также собрал на Кубе, просто VCP. Подключаю, неизвестный девайс. Что может быть?

Приглашаем 30 ноября всех желающих посетить вебинар о литиевых источниках тока Fanso (EVE). Вы узнаете об особенностях использования литиевых источников питания и о том, как на них влияют режим работы и условия эксплуатации. Мы расскажем, какие параметры важно учитывать при выборе литиевого ХИТ, рассмотрим «подводные камни», с которыми можно столкнуться при неправильном выборе, разберем, как правильно проводить тесты, чтобы убедиться в надежности конечного решения. Вы сможете задать вопросы представителям производителя, которые будут участвовать в вебинаре

Наличие USB порта в современных микроконтроллерах открывает широкие возможности для самостоятельного изготовления разнообразных управляемых с компьютера устройств. На практике, однако, выясняется, что поставляемые производителем библиотеки для работы с USB нуждаются в доработке. Если вам интересен опыт подобной доработки для двух популярных семейств МК — добро пожаловать под кат.

Постановка задачи

STM32 — просто добавь кода

Итак, берем за основу готовый пример, который перекладывает данные из USB в последовательный порт микроконтроллера и обратно. Последовательный порт нам не понадобится, а данные мы будем просто перекладывать из входного потока в выходной, то есть реализуем эхо. С помощью PuTTY убеждаемся, что оно работает. Но этого недостаточно. Для обмена данными с устройством нам понадобится слать много больше одного символа за раз. Пишем тестовую программу на питоне, которая шлет посылки случайной длины и вычитывает ответ. И тут нас ждет сюрприз. Тест работает, но недолго, после чего очередная попытка чтения либо зависает навсегда, либо завершается по таймауту, если он выставлен. Исследование проблемы с помощью отладчика показывает, что МК таки отослал все полученные данные, причем последняя посылка имела длину 64 байта. Что же произошло?

USB-стек на хост-системе имеет многослойную структуру. На уровне драйвера данные получены, но остались у него в кэше. Драйвер передает закэшированные данные приложению тогда, когда приходят новые данные и вытесняют старые, либо когда драйвер узнает, что новых данных пока ожидать не следует. Откуда же он может получить это знание? USB шина передает данные пакетами. Максимальный размер пакета в нашем случае как раз 64 байта. Если в очередном пакете данных пришло меньше, значит новых данных пока можно не ждать, и это является сигналом для того, чтобы передать приложению все полученные данные. А если данных пришло ровно 64 байта? На этот случай в протоколе предусмотрена посылка пакета нулевой длины (ZLP), который и является сигналом прерывания потока. Получив его, драйвер понимает, что новых данных пока ожидать не следует. В нашем случае он его не получил потому, что разработчики USB стека для STM32 про ZLP просто ничего не знали.

Вторая проблема, которую разработчики USB-стека незаслуженно обошли вниманием — что делать с данными, которые были получены по USB, если их некуда девать, т.к. входной буфер переполнен. По большому счету, их вообще не волновала проблема входного буфера — они предполагали, что все полученные данные немедленно обрабатываются, что, конечно-же, не всегда может быть выполнено. В USB протоколе на случай, если данные не могут быть получены, предусмотрен ответ NAK — отрицательное подтверждение. После такого ответа хост просто посылает данные еще раз. Если мы хотим избежать переполнения входного буфера, нам нужно в случае, если в нем нет места для полной посылки (64 байта), переводить канал в состояние NAK, что обеспечивает автоматический ответ NAK на все входящие пакеты.

Tiva C — слоеный пирог с багами

Я работаю во встроенном приложении для STM32F401RBT6 и пытаюсь установить соединение с PC (Windows 10), но устройство не распознается системой. Код, который я сгенерировал с помощью STMCubeMX и отладил с помощью Atollic , не работает. Я видел и пытаюсь воспроизвести несколько примеров, но все работает. В коде у меня есть все библиотеки, которые я считаю необходимыми.

archives
archives2

У меня есть этот архив, сгенерированный STMCubeMX для связи CDC , но я новичок и не знаю, что мне нужно изменить в коде для USB, который будет распознан системой. Кто-нибудь может мне помочь?

2 ответа

Я купил USB к последовательному кабелю, который утверждает, что он соответствует CDC. Но значение bInterfaceClass в дескрипторе интерфейса равно 0xFF(что зависит от конкретного поставщика). Я ожидал, что это будет 0x02 (связь и управление CDC). В диспетчере устройств я обнаружил, что загружаемые.

Я хочу USB CDC как часть моего проекта, что является самым простым способом сделать это ? я попробовал какой-то проект в keil arm, но скорость очень низкая, и с этим так много проблем !

Помимо точки из супа ( неудачный malloc, вызванный кучей, которая по умолчанию составляет только 0x200), некоторые версии Windows имеют проблему с кодированием строки в Примере.

В usbd_cdc_if.c вы должны добавить:

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

Внутри функции USBD_CDC_Init(..) есть функция malloc, которая выделяет около 540 байт памяти в куче.

Это не было учтено с CubeMX при создании кода .

Таким образом , по крайней мере, вы должны определить размер кучи с учетом этих дополнительных байтов, чтобы порт USB CDC работал.

Похожие вопросы:

Для проекта я делаю клавиатуру USB, у нее есть несколько кнопок, и клавиши должны быть программируемыми. Я выбрал ATXMega32C4, так как он имеет поддержку USB, а также удобную библиотеку ASF в Atmel.

Я построил код из STM32CubeF4 для примера CDC USB. Я добавил недостающий код приема для CDC_Receive_FS() в usbd_cdc_if.c. Я загрузил это в свое открытие STM32F4, и оно работает. Персонаж набирается.

Библиотека микрочипов для приложений предоставляет демонстрационный код для USB - CDC basic demo & CDC device serial emulator. Я обнаружил, что все они связаны с коммуникацией microchip - USB.

Я купил USB к последовательному кабелю, который утверждает, что он соответствует CDC. Но значение bInterfaceClass в дескрипторе интерфейса равно 0xFF(что зависит от конкретного поставщика). Я.

Я хочу USB CDC как часть моего проекта, что является самым простым способом сделать это ? я попробовал какой-то проект в keil arm, но скорость очень низкая, и с этим так много проблем !

Я использую модем USB с моей платой Linux, и Kernel создает 4 виртуальных последовательных порта(CDC-ACM), когда я подключаю модем. и имя последовательного порта asr, как ttyUSB0 - ttyUSB3. Но эти.

Я нашел большое количество примеров, но ничего о том, как это сделать properly из STM32MXCube. Как создать скелетный код из STM32CubeMX для USB CDC virtual COM port communications (если возможно.

Я использую stm32L151 для связи с PC по USB CDC. Я использовал библиотеки stm32 HAL для создания своего проекта. Я обнаружил, что usb отправляет данные с интервалом в 1 мс, и каждый раз отправляется.

я запрограммировал свою плату stm32f103 blue-pill с протоколом USB-CDC Я могу читать и писать на этом порту Но после выполнения аппаратного сброса порт COM недоступен Я должен отключить соединение.

В чем дополнительное преимущество разработки полного драйвера UMDF windows, если устройство CDC обнаружено как виртуальный порт COM?. У меня есть некоторый опыт работы со встроенными примерами.

Отладочную плату ипользуем ту же: STM32F4-DISCOVERY.

Проект создаём из проекта I2CLCD80. Назовем его USB_OTG_CDC. Запустим проект в Cube, включим USB_OTG_FS в режим Device_Only

image00

В USB_DEVICE в разделе Class For FS IP выберем пункт Communication Device Class (Virtual Port Com).

image02

Лапки портов PD4-PD7, PB8, PB9 отключим, это пережиток прошлых занятий

image01

В Clock Configuration выберем следующие делители (нажмите на картинку для увеличения изображения)

image04_0500

В Configuration ничего не трогаем, т.к. прерывания там выставились сами.

Сгенерируем и запустим проект, подключим lcd.c и настроим программатор на автоперезагрузку.

У нас скорей всего устройство установится с ошибкой (код 10)

image03

Есть несколько типов решений, мне понравился именно этот, т.к. более простой: в файле usbd_cdc.h заменим размер пакета, вместо 512 напишем 256 в данной строке:

Соберём, прошьём и увидим, что ошибка исчезла.

Начнём писать код.

Сначала попытаемся передать данные на ПК.

Для этого мы сначала откроем файл usbd_cdc_if.c и исправим там в 2х строчках 4 на 64

В файле main.c закомментируем весь пользовательский код кроме инициализации и очистки дисплея

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

Также в main.c подключим файл usbd_cdc_if.h для видимости функций приема и передачи

/* USER CODE BEGIN Includes */

Немного изменим в главной функции строковую переменную, убавив в ней размер и добавив префикс tx

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

В файле usbd_cdc_if.c добавим прототип функции передачи, скопировав объявление из реализации данной функции в том же файле

/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);

/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

В main() внесём данные в строку

/* USER CODE END 2 */

CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));

/* USER CODE END WHILE */

Соберём код, прошьём контроллер и посмотрим результат в терминальной программе.

Вроде передать нам что-то удалось. Теперь попробуем что-нибудь принять. Здесь чуть посложнее, т.к. для этого используется уже обработчик прерывания, коим является в файле usbd_cdc_if.c функция CDC_Receive_FS.

Добавим ещё одну строковую глобальную переменную в main()

/* USER CODE BEGIN PV */

/* USER CODE END PV */

Объявим её также и в файле usbd_cdc_if.c

/* USER CODE BEGIN PRIVATE_VARIABLES */

extern char str_rx[21];

/* USER CODE END PRIVATE_VARIABLES */

В функцию CDC_Receive_FS в этом же файле добавим некоторый код и кое-что закомментируем

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

/* USER CODE BEGIN 6 */

Добавим переменную в main()

/* USER CODE BEGIN 1 */

Занесенные в наш буфер данные попробуем вывести на дисплей, для этого в бесконечном цикле в функции main() добавим определённый код

CDC_Transmit_FS((unsigned char*)str_tx, strlen(str_tx));

Соберём проект. Прошьём код и посмотрим результат, вводя в терминальной программе и отправляя в порт USB какие-нибудь строки.

STM32 HAL. USB. Virtual Com Port

22 комментария на “ STM Урок 33. HAL. USB. Virtual Com Port ”

Просто измените размер кучи (Minimum Heap Size) в настройка CubeMX. Вместо значения 0x200 задайте 0x400.

И комп увидит устройство без ошибок.

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

Пардон, очепятка вышла. Не компилятору, а функции malloc.

Спасибо, так действительно проще.

Спасибо.Я сделал так.В хидер usbd_cdc_if.h добавил две строчки
extern uint8_t UserRxBufferFS[1000];
uint8_t receiveBufLen;
В метод CDC_Receive_FS добавил перед return receiveBufLen = *Len;
И в main ловил данные просто одним условием
if(receiveBufLen > 0)// если получены данные от ПК
HAL_Delay(250);
CDC_Transmit_FS((uint8_t*) UserRxBufferFS,receiveBufLen);
// эхо для наглядности
receiveBufLen = 0;// сброс получения
>
Всё просто,а UserRxBufferFS чистить не нужно от мусора,он сам чистится.

может в usbd_cdc_if.c ?

Ох, видимо сперва надо читать коментарии, прочитал тот что выше.

Скорей всего придется делать конкатенацию передаваемых строк с помощью strcat. Была аналогичная проблема при использовании CDC. Автор применял этот метод в одном из уроков.

Здравствуйте
А если я хочу передавать данные с микроконтроллера на компьютер?

Константин:
А мы их туда и передали.

Установил различные драйвера VCP от STM, но при этом плата не определяется при подключении её к компьютеру. только виден STLink Virtual COM Port. Кто уже сталкивался с такой проблемой.

Оказалась, что проблема с дровами. Надо их полностью сносить и устанавливать заново.

You can use(for example):

where ADC_Data is your ADC value.

могу скачать драйвера для виртуального ком порта. У меня STM32F415RG, может есть у кого?

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