Двигаемся дальше! Какой 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!

