5.9 KiB
Компонент USB Virtual COM Port (DS_VirtualComPort)
Готовый к интеграции программный компонент на базе официального стека STMicroelectronics USB Device Middleware (класс CDC — Communication Device Class).
Репозиторий полностью оптимизирован: из него удалены все неиспользуемые USB-классы (Audio, HID, MSC), а файлы низкоуровневой конфигурации (usbd_conf.c/.h) и пользовательского интерфейса (usbd_cdc_if.c/.h) перенесены прямо внутрь компонента. Это позволяет разворачивать виртуальный COM-порт в проектах с любой архитектурой (HAL/LL) без CubeMX-генерации кода самого USB.
📌 Структура оптимизированного компонента
Library/DS_VirtualComPort/
├── Class/
│ └── CDC/
│ ├── Inc/usbd_cdc.h, usbd_cdc_if.h
│ └── Src/usbd_cdc.c, usbd_cdc_if.c # Интерфейс приема/передачи данных
└── Core/
├── Inc/usbd_core.h, usbd_conf.h ...
└── Src/usbd_core.c, usbd_conf.c # Конфигурация аппаратного USB-драйвера
🚀 Способ добавления в проект (Git Submodule)
1. Подключение подмодуля
Выполните команду в корневом каталоге вашего проекта:
git submodule add https://domstudent.ru Library/DS_VirtualComPort
2. Автоматическое обновление сборки CMake
Запустите PowerShell-скрипт автоматизации из вашей библиотеки утилит (DS_UpdateCMakeList):
cd tools/
./UpdateCMakeList.ps1
Скрипт автоматически найдет заголовочные файлы и исходный код (включая usbd_cdc_if.c и usbd_conf.c), после чего корректно пропишет их в конфигурацию вашего CMakeLists.txt.
🛠 Настройка тактирования (Clock Configuration)
Для успешной работы USB требуется стабильная частота тактирования шины строго 48 MHz. В микроконтроллерах с поддержкой безкварцевого USB (например, STM32F042 / STM32G4) это реализуется через внутренний осциллятор HSI48.
Пример конфигурации тактирования через LL-драйверы:
void SystemClock_Config(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);
LL_RCC_HSI48_Enable(); // Включаем внутренний генератор 48 МГц
while(LL_RCC_HSI48_IsReady() != 1) {} // Ожидаем стабилизации
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI48); // Назначаем системным источником
LL_SetSystemCoreClock(48000000);
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_HSI48); // Назначаем источником тактов USB
}
💻 Интеграция и пример использования в main.c
Поскольку конфигурация скрыта внутри подмодуля, запуск USB-стека в пользовательском коде сводится к четырем последовательным вызовам функций в секции инициализации периферии.
#include "usbd_core.h"
#include "usbd_cdc_if.h"
/* Глобальные хэндлеры управления стеком */
USBD_HandleTypeDef hUsbDeviceFS;
extern USBD_DescriptorsTypeDef Class_Desc;
int main(void)
{
// Буфер сообщения (символ конца строки \n обязателен для терминалов)
uint8_t TxMessageBuffer[] = "MY USB IS WORKING! \r\n";
HAL_Init();
SystemClock_Config();
// Инициализация ваших таймеров и портов ввода-вывода (MX_GPIO_Init, MX_TIM2_Init...)
/* --- РУЧНОЙ ЗАПУСК СТЕКА USB VCP --- */
USBD_Init(&hUsbDeviceFS, &Class_Desc, DEVICE_FS); // Инициализация ядра USB
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC); // Регистрация класса CDC
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS); // Привязка функций интерфейса
USBD_Start(&hUsbDeviceFS); // Физический старт USB-устройства
while (1)
{
/* Отправка данных на ПК */
// Передаем указатель на буфер и его длину (исключая нуль-терминатор строки)
CDC_Transmit_FS(TxMessageBuffer, sizeof(TxMessageBuffer) - 1);
HAL_Delay(500); // Период отправки пакетов
}
}
📋 Справочник API функций
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
Основная функция верхнего уровня для отправки массива данных на ПК.
Buf: Указатель на массив байт для отправки.Len: Размер отправляемого пакета данных в байтах.- Возвращаемое значение:
USBD_OK(0) при успешной постановке пакета в очередь отправки, илиUSBD_BUSY(1), если предыдущий пакет еще не успел улететь по шине.