Первая итерация

This commit is contained in:
2026-06-27 00:39:04 +03:00
parent 2009035bb4
commit c4ec2b64cd
12 changed files with 951 additions and 180 deletions
+110
View File
@@ -0,0 +1,110 @@
# Компонент 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.
## 📌 Структура оптимизированного компонента
```text
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. Подключение подмодуля
Выполните команду в корневом каталоге вашего проекта:
```bash
git submodule add https://domstudent.ru Library/DS_VirtualComPort
```
### 2. Автоматическое обновление сборки CMake
Запустите PowerShell-скрипт автоматизации из вашей библиотеки утилит (`DS_UpdateCMakeList`):
```powershell
cd tools/
./UpdateCMakeList.ps1
```
Скрипт автоматически найдет заголовочные файлы и исходный код (включая `usbd_cdc_if.c` и `usbd_conf.c`), после чего корректно пропишет их в конфигурацию вашего `CMakeLists.txt`.
---
## 🛠 Настройка тактирования (Clock Configuration)
Для успешной работы USB требуется стабильная частота тактирования шины строго **48 MHz**. В микроконтроллерах с поддержкой безкварцевого USB (например, STM32F042 / STM32G4) это реализуется через внутренний осциллятор **HSI48**.
Пример конфигурации тактирования через LL-драйверы:
```c
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-стека в пользовательском коде сводится к четырем последовательным вызовам функций в секции инициализации периферии.
```c
#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), если предыдущий пакет еще не успел улететь по шине.