Pull to refresh

Нюанс, из-за которого ваш I2S не работает…

Reading time3 min
Views14K

... и о котором почему-то нигде не написано.

Некоторое время назад я сел осваивать интерфейс I2S для работы с аудио ЦАПом высокого качества. За спиной у меня уже был большой опыт работы с различными SPI микросхемами, I2C микросхемами, методы работы в блокирующем режиме, неблокирующем режиме через прерывания, неблокирующем режиме через DMA. В общем, мне казалось, что меня уже ничем не удивить. Но за это мы и любим мир электроники и компьютеров — он сможет удивить даже самого искушенного разработчика.

TI PCM1789
TI PCM1789

Я использую библиотеку CMSIS, а информацию о работе с устройством смотрю напрямую в RefManual, чтобы брать информацию из первых рук. I2S является частью SPI модуля в моем любимом STM32F446. Первое ощущение было, что отличаются только пины, но суть от этого не меняется. Ты кладешь данные в регистр отправки, а устройство само все отрабатывает, как ему и положено.

Я настроил модуль, запустил программу и даже проверил на осциллографе временные диаграммы. Все было ровно. Только вот ЦАП вместо какой‑то тестовой ерунды выдавал 0. Что же, пора разбираться.

Я начал читать, что пишут люди в интернете. Люди в интернете не писали ничего нового, чего не было написано в рефмануале stm32. Значит, проблема в железе.

Я купил другой I2S ЦАП на случай, что мой по какой‑то причине был испорчен. Это также не помогло.

TI PCM5102
TI PCM5102

Пришлось писать моему другу, который уже заводил I2S ЦАП. Я описал ему свою проблему, он также не понял, почему у меня ничего не работает. Однако он любезно сгенерировал для меня тестовую прошивку под мой камень и мои пины.

Прошивка запустилась, начала генерировать какой‑то синус с неверной записью знаковой информации (но было видно, что друг хотел сгенерировать синус). И тут вскрылся маааааааленький нюанс, про который все почему‑то забыли написать.

SPI, I2C, USB, USART и другие протоколы работают по принципу «инициатива волнует инициатора». У вас есть SPI ЦАП. Вы в него шлете команду «установи значение напряжения в V/2», к примеру. А дальше тысячу лет молчите. ЦАП молча стоит и удерживает то значение, которое ему сказали держать. До тех пор, пока его не обесточат, конечно. Такая же ситуация и в других протоколах. Они общаются только тогда, когда есть что сказать. А вот I2S не такой!

В I2S‑коммуникации Мастер должен непрерывно, да еще и с правильными клоками, постоянно слать то значение, которое он хочет, чтобы ЦАП удерживал. Без этого, как вы понимаете, вообще ничего работать не будет.

Занимать процессор подобной бесполезной работой неэкономично. Поэтому DMA заставляют заниматься этим. Модулю DMA показывают 2 ячейки в памяти (ведь I2S стерео): вот тут будут лежать значения I2S ЦАПа. DMA‑канал запускают в циклический режим, чтобы он непрерывно валил числа из памяти камня внутрь ЦАПа. Вы в каком‑то своем темпе меняете данные внутри памяти (да хоть вообще не меняете), а DMA с пеной изо рта шлет их в эфир. И все работает отлично, если клоки настроены и тому подобное.

Перед написанием данной статьи я еще раз проверил выдачу гугла по теме I2S, но так и не нашел описания этого маленького нюанса. Поэтому и публикую текст. Если вы это знаете, дальше вам нужны любые статьи по теме, либо реф мануал на камень.

Я же в итоге под свое устройство выбрал четырехканальный 16-битный SPI ЦАП. Но это уже совсем другая история, которую я планирую рассказать в другом посте.

Спасибо за внимание и удачи в ваших исследованиях!

Tags:
Hubs:
Total votes 44: ↑35 and ↓9+33
Comments48

Articles