|
Полифонический FM Синтезатор с STM32F031
Статьи публикуются по мере поступления. Для упорядоченного тематического
поиска воспользуйтесь блоком "Карта сайта"
Я построил MIDI-совместимый многофонический FM-синтезатор, используя 32-битный микроконтроллер ARM Cortex M0 и аудиокодек. Это было для меня уроком.
Обратите внимание, что для этого устройства нет единого тона . Почти каждый параметр настраивается «на лету».
Окончательная схема приведена ниже. Я буду объяснять систему по частям.
Микроконтроллер
Я использовал ARM Cortex M0 ядро STM32F031 для проекта. В ядрах Cortex M0 нет ничего сверх того, что имеет аппаратный множитель 32x32 для целей DSP. У Cortex M3 и M4 / M4F есть конкретные инструкции DSP, и они были бы гораздо более полезными для такой сложной вычислительной задачи, но я просто хотел попробовать, что можно сделать с недорогим чипом ARM начального уровня. В этом конкретном микроконтроллере также имеются модули I2S и DMA, которые необходимы для этого проекта. Для системных часов я использую внутренний PLL для генерации 48 МГц тактовых импульсов, но я оставил дополнительный XTAL для будущего использования. R1, R2, R3 и R4 используются для замедления краев сигналов I2S, чтобы немного снизить высокочастотный шум. Я положил 49,9 Ом в реальную цепь.
Аудиокодек
Это 2-канальный, 24-бит, 192 кГц дискретизатор с частотой дискретизации, поддерживающий Cirrus Logic (ранее Wolfson).
Выходной фильтр
Операционный усилитель, который я использовал, - MCP6002. Они имеют достаточно пропускную способность и уровень шума. Это фильтр нижних частот Sallen Key второго порядка, за которым следует пассивный фильтр низких частот с одним порядком. Значения компонентов должны быть правильно выбраны для лучшей кривой отбраковки, но я использовал 4,7 k для резисторы и 4,7nF для конденсаторов, которые дают примерно 7,3 кГц -3db точки.
Источник питания
LDO совместим с универсальными 5-контактными SOT23 LDO. В частности, я использовал Micrel MIC5317. Есть два отдельных регулятора, один для микроконтроллера, другой для фильтра с кодеком + выход. На входном этапе LDO также имеются ферриты, чтобы отфильтровывать некоторые высокочастотные шумы настолько, насколько они могут.
Midi-интерфейс
Оптрон развязывает приборную землю с землей платы управления и устраняет возможные проблемы с заземлением. Кроме того, оптрон действует как преобразователь уровня напряжения между любыми MIDI-клавиатурами посылает 3V3 уровень на микроконтроллер.
В оборудовании v0.1 я смешал вывод №4 и контакт №5 разъема. Я закрепил его с помощью ножей + патч-проводов на печатной плате.
Печатный монтаж
Я разделил аналоговую и цифровую часть разметки и соединил две части по небольшому мостику и передал каждый необходимый сигнал между двумя частями только сверху этого моста.
Прошивка
Репозиторий прошивки GitHub: https://github.com/kehribar/stm32f031_template/tree/master/_synth. Эта прошивка является частью моего испытания по созданию общей структуры для микроконтроллера STM32F031. Я использовал компилятор GCC, который я скачал с http://launchpad.net/gcc-arm-embedded .
DMA
DMA используется для передачи данных от микроконтроллера к кодеку. DMA на STM32F031 не поддерживает двойную буферизацию , поэтому мне пришлось обмануть систему, чтобы эмулировать двойную буферизацию. Сам DMA имеет прерывания передачи и полные прерывания. В цикле while (1) я выполняю опрос для этих двух флагов прерывания и заполняю первую половину или вторую половину фиксированного буфера линейщика, исходя из того, какой флаг установлен. Что касается DMA, то она завершается началом массива после его завершения, но в то же время я меняю содержимое буфера без каких-либо проблем с порчей данных благодаря флагам индикации. I2S периферийное устройство SMT32F031 поддерживает 24-битные передачи, но оно плохо работает с DMA. Для каждого образца сначала нужно сдвинуть данные 8 бит влево, выровнять их до 32 бит. Во-вторых, вам нужно поменять более высокие 16 бит и младшие 16 бит в этой переменной. Скорее всего, это связано с тем, как DMA считывает память. Я узнал об этом по некоторому количеству сеансов отладки. Следующий пример кода фиксирует 24-разрядные выровненные по правому краю подписанные данные в надлежащем формате, так что при чтении DMA фактический результат будет тем, что вы ожидаете.
static inline int32_t convertDataForDma_24b ( const int32_t data ) { uint32_t result ; uint32_t shiftedData ; shiftedData = data << 8 ; result = ( shiftedData & 0xFFFF0000 ) >> 16 ; result |= ( shiftedData & 0x0000FFFF ) << 16 ; return ( int32_t ) result ; }
Так много для недорогого микроконтроллера. :)