Детектор Tayloe и цифровая обработка сигналов #12 составное USB устройство на STM32

Автор: | 13.02.2026

Двигаемся дальше! Какой SDR проект приемника/трансивера без полноценного CAT? CAT (Computer Aided Transceiver) в связной аппаратуре — это система и протокол для управления устройством с компьютера. Мы уже научились на STM32 реализовывать передачу аудио потока через USB. Данный вариант хорош тем, что полностью исключает использование аналоговых кабелей для передачи аудио сигнала в ПК, т.к. через USB данные идут в цифре, а значит решаем проблемы всевозможных наводок и прочего негатива в передаваемом от устройства к устройству сигнале, в итоге сигнал на ПК от устройства передатчика поступает на устройство приемник именно в том виде, в котором отправлен.

Тренироваться будем на STM32F401CCU6, задача — реализовать составное USB устройство включающее в себя классы CDC (Communication Device Class) — виртуальный COM порт и аудио устройство записи на хосте, хост в нашем случае — персональный компьютер с OS Windows, линуксоподобных систем у меня нет, но и там должно все работать.

Кто работал с USB на STM32 знает, что ST не жалует пользователей удобным механизмом реализации составного USB устройства, в STM32СubeMX(IDE) просто можно выбрать только один класс, а нам надо как минимум два! На помощь нам придет замечательная библиотека TinyUSB. Эта библиотека поддерживает большой выбор устройств для работы с USB стеком. И немаловажный момент в том, что при добавлении нового функционала МК через CubeMX при генерации кода, не будут затираться наши труды в написании кода для USB!

В релизе 2.0 среды разработки STM32CubeIDE уже физически убран конфигуратор проекта STM32CubeMX, а т.к. я уже обновился, то приходится новый проект начинать именно в STM32CubeMX. Начнем…

1. Создаем минимально необходимый проект на STM32F401CCU6, настраиваем тактирование

отладку

и режим коммуникации выбираем USB

включаем глобальное прерывание от USB

Классы для USB в разделе Middleware and Software Pacs ни какие не выбираем!

Далее настраиваем необходимые клоки

В завершении использования STM32CubeMX настраиваем параметры проекта под STM32CubeIDE

Генерируем проект и файл отчета в PDF файл, чтобы не открывать постоянно CubeMX для посмотреть, что и как мы настроили

2. Скачиваем с репозитория исходники TinyUSB

В корневой папке проекта создаем папку TinyUSB, в нее копируем из исходников только папку ..\tinyusb-master\src\.

Теперь надо настроить TinyUSB, для этого необходимо два файла, первый tusb_config.h в нем описываются параметры МК и необходимые классы USB стека. Второй файл usb_descriptors.c здесь описываются дескрипторы USB. Эти файлы я разместил в папке TinyUSB, структура проекта у меня такая получилась

Через контекстное меню по папкам проекта в CubeIDE  добавляем пути папок TinyUSB и TinyUSB\src через пункт Add/Remove include path…

В параметрах проекта добавляем эти же пути на вкладке Source Location, иначе проект не соберется

3. Реализуем необходимые функции — наш пример будет при подключении к хосту генерировать белый шум на уровне -96dBFS, и по командам через виртуальный COM порт включать/отключать генерацию квадратурного I/Q сигнала на частоте +1кГц и уровнем S9+20 по шкале S-metr. При подключении к USB светик на плате МК будет гореть, при старте генерации моргать, при отключении от USB гаснуть. Все эти функции реализованы в следующих файлах:

  • usb_cdc.h
  • usb_cdc.c
  • usb_audio.h
  • usb_audio.c
  • audio_generator.h
  • audio_generator.c
  • led_pcb.h
  • led_pcb.c

Эти файлы располагаем в соответствующих папках проекта Core/Inc и Core/Src. Весь код прокомментирован, разобраться, что и как реализовано не составит труда!

4. Добавляем вызовы, в main.c, в пользовательской секции подключаем инклюды
добавляем инициализацию TinyUSB

и в файле stm32f4xx_it.c изменяем колбэк вызываемый включенным прерыванием в п.1 void OTG_FS_IRQHandler(void)

и в секции пользовательских инклюдов этого файла подключаем TinyUSB строчкой #include «tusb.h».

Теперь собираем проект, прошиваем МК, подключаем к USB, наблюдаем, что светик на плате МК загорелся, проверяем что у нас там появилось в диспетчере устройств

не забываем, что в дескрипторах наше аудио устройство записи объявлено как Радиоприемник, а значит по умолчанию Windows подобные устройства отключает, открываем диспетчер аудио устройств и включаем наше устройство

для проверки открываем терминал и наше приложение для анализа квадратурных сигналов I/Q, в терминале выбираем COM порт на котором определился МК, подключаемся, видим приветственное сообщение от устройства и список команд. В приложении выбираем наш Радиоприемник как входное аудио устройство и запускаем захват

наблюдаем шумовую полку на уровне ~120dB, а где же обещанные -96dBFS? Ответ как всегда можно найти в умных книжках, физика шумового спектра следующая

пиковый уровень отсчёта +/-1, т.е. 20·log₁₀(1/32767) = -90.3 — максимальная амплитуда одного отсчёта в dBFS

а усреднённый уровень после FFT -110..-125 dBFS, т.е. энергия белого шума «размазывается» по всему спектру, что мы имеем при FFT равным 8192 и частоте дискретизации 48 kHz, как в нашем случае:

  • ширина бина FFT 48000 / 8192 ≈ 5.86 Гц;
  • отсчётов на бин за 100 мс 48000 × 0.1 / 5.86 ≈ 819 отсчётов;
  • снижение уровня от усреднения 10·log₁₀(819) ≈ 29.1 дБ;
  • итоговый уровень в спектре -90.3 dBFS — 29.1 дБ ≈ -119.4 dBFS.

Теперь включаем генерацию на МК по команде через COM порт

Видим наш сигнал на частоте +1 kHz от нуля на комплексном спектре.

Спрашивается, зачем генерировать шум? В первую очередь — это имитация работы приемника! Второе, если мы не будем генерировать искусственный шум, нижняя полка при отсутствии сигнала у нас будет на спектре в виде ровной линии на уровне примерно -240 dB, потому, что в аудио потоке сигнала одни нули. А если подадим сигнал, то увидим гармоники сигнала с максимальным уровнем примерно -95…-120 dB, их отголоски, которые не маскируются шумом мы и наблюдаем на спектре.

Откуда берутся гармоники в генерируемом сигнале в данном случае? Гармоники даже при амплитуде -53 dBFS видны из-за недостаточной разрядности (квантования), используется всего 147 уровней, можно их уровень снизить ниже шумовой полки, но в данном примере это без необходимости.

Данная реализация составного USB устройства очень просто портируется на другую серию STM32! В файле tusb_config.h просто меняем серию МК, например для H7 меняем  определение МК с OPT_MCU_STM32F4 на OPT_MCU_STM32H7 и согласно п.4 меняем колбэк USB уже в файле stm32h7xx_it.c аналогичным образом

конечно же не забываем в этом файле добавить инклюд #include «tusb.h», вот и все портирование!

В завершении исходный код проекта под STM32CubeIDE v2.0

Продолжение следует…

73!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *