• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вопрос Генератор звука STM32F3-Discovery, ESP8266 и I2S

RRRLock

New member
Доброго времени суток!
Есть задача сделать генератор звуковых сигналов с помощью платы STM32F3-Discovery, затем по интерфейсу I2S передавать аудио-сигнал в ESP8266, по радио-каналу с использованием протокола UDP пересылать сигнал в компьютер и воспроизводить звук. Формат данных 24 бита, частота дискретизации 48 кГц. STM32F3 - мастер-передатчик, ESP - слэйв-приемник.
Пишу прошивку в Eclipse с использованием UDK. В папке с примерами есть проект I2S-Demo. Попробовал подправить проект под свои нужды, но столкнулся со следующими проблемами:

1. DMA отказывается работать в непрерывном режиме с кольцевым буфером. Буферы заполняются отсчетами, а дальше идут сплошные нули. Почему-то прошивка каждый раз перезапускается заново.

2. Данные с STM-ки приходят не полностью. Часть сообщения теряется, такое ощущение, что входной канал I2S в ESP8266 запрограммирован под другую тактовую частоту и частоту дискретизации. Так же есть мысль, что нет синхронизации по CLK, поскольку затактировал I2S в STM от PLL без кварца. Так же частота дискретизации получилась не 48 000 Гц, а 48 676 Гц. Может быть в этом дело?

Подскажите пожалуйста в чем может быть проблема?
 
Последнее редактирование:

RRRLock

New member
Занимался другим проектом и получил подвижки в этом. Запустил в непрерывном режиме передачу данных с использованием DMA с STM32F3-Discovery на модуль ESP8266 (ESP-07).
STM32F3 - master transmitter, ESP8266 - slave receiver. Формат передаваемых данных 24 бита, MSB-first, частота сэмплирования 48 кГц, размер одного передаваемого буфера 128 отсчетов. Каждая ячейка буфера передатчика заполнена тестовым числом 0x0300bb55. Результаты в виде 10 отчетов приемного буфера вывожу на терминал. Получается вот такая вот картина. Нечетные ячейки буфера приемника заполняются "почти" таким же числом, которое я отправлял, а вот четные ячейки почему-то заполнены удвоенным числом.

Ищу ошибку в инициализации I2S на ESP8266. Может у кого-то ещё какие мысли есть, почему происходит умножение на 2 и как это исправить?
Делители для тактирования I2S в вышесказанном режиме настроил так:
Код:
CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
                        (I2S_BITS_MOD<<I2S_BITS_MOD_S)|
                        (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
                        (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));

    SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
                        I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
                        ((13&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
                        ((4&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S)|
                        (15<<I2S_BITS_MOD_S));
 

Вложения

Garmin

Member
Подобную проблему оцифровки звука я решил по другому. I2S принимается в STM32, а затем по SPI протоколу передаётся в ESP8266. Причём обмен ведётся в обе стороны. ESP8266 работает как SPI slave, шина данных мультиплексирована. Пакеты по 64 байта, так как у SPI такой объём буфера. Ничего не теряется. Сейчас тружусь над передачей по WiFi. UDP меня не удовлетворил (есть потери), занимаюсь TCP, но с кучей кривых примеров и с разными реализациями передачи есть проблемы в понимании сути процесса.
 

RRRLock

New member
Подобную проблему оцифровки звука я решил по другому. I2S принимается в STM32, а затем по SPI протоколу передаётся в ESP8266. Причём обмен ведётся в обе стороны. ESP8266 работает как SPI slave, шина данных мультиплексирована. Пакеты по 64 байта, так как у SPI такой объём буфера. Ничего не теряется. Сейчас тружусь над передачей по WiFi. UDP меня не удовлетворил (есть потери), занимаюсь TCP, но с кучей кривых примеров и с разными реализациями передачи есть проблемы в понимании сути процесса.
У меня тоже была идея воспользоваться SPI, но столкнулся с рядом препятствий:

1. У HSPI сигнал CS заведен на GPIO15, который должен быть подтянут через резистор к земле. Можно выбрать 3 других вывода под CS.
Какой выбрали вы? У меня модуль ESP-07, проект делаю в Eclipse с помощью UDK, для программирования и отладки использую плату USB-TTL, GPIO0 заведен на DTR, GPIO1 занят под TX0, а GPIO11 находится под экраном. Можно конечно снять экран и подпаяться аккуратненько или взять ESP-12E, который у меня тоже имеется, на котором выведен GPIO11.

2. Какой API использовать для проекта с FreeRTOS? Попутно хочу спросить, есть ли способ обойтись без FreeRTOS для непрерывной обработки данных?
 

Garmin

Member
Я сразу использовал ESP-12. Подключение:
* Обмен данными по SPI1 в slave режиме
* GPIO12 - данные MISO и MOSI
* GPIO13 - REQ GPIO OUT флаг запроса от ESP8266 на передачу данных
* GPIO14 - CLK
* GPIO15 - CS
* GPIO4 - CS GPIO IN для разрешения конфликтов
Резистор нужен только во время старта, а в это время IO порты STM32 находятся в высокоимпедансном состоянии. Так что ничего не мешает модулю стартовать.
Пишу также под UDK, но со своим файлом описания периферии. Он выложен в соседней теме.
Принцип обработки данных никак не связан с FreeRTOS. Я писал и так, и так. Сейчас пишу без него.
 

RRRLock

New member
Принцип обработки данных никак не связан с FreeRTOS. Я писал и так, и так. Сейчас пишу без него.
Как вы работаете с непрерывным приемом данных по SPI? Используете бесконечный цикл? Как тогда разбираетесь с watchdog?

В SDK programming guid написано:
Using non-OS SDK which is single-threaded, the CPU should not take long to execute tasks:
‣ If a task occupies the CPU too long, ESP8266 can't feed the dog, it will cause a watchdog
reset;
‣ If interrupt is disabled, CPU can only be occupied in us range and the time should not be
more than 10 us; if interrupt is not disabled, it is suggested that CPU should not be
occupied more than 500 ms.
Не стал с этим разбираться и перешел на проект с FreeRTOS. Теперь вот зерно сомнения во мне после ваших слов))
 

Garmin

Member
Как вы работаете с непрерывным приемом данных по SPI? Используете бесконечный цикл? Как тогда разбираетесь с watchdog?
Не стал с этим разбираться и перешел на проект с FreeRTOS. Теперь вот зерно сомнения во мне после ваших слов))
Именно глупые примеры с опросом и задержками в циклах сбивают всех с толку.
Мне посоветовали работь по событиям. Поставил прерывания и коллбэки на события в main_init () и у меня нет цикла основной программы. Процессор занимается своими делами.
Правда, пришлось подрихтовать свою парадигму программирования, и отслеживать развитие событий в разных частях программы.
 

RRRLock

New member
Именно глупые примеры с опросом и задержками в циклах сбивают всех с толку.
Мне посоветовали работь по событиям. Поставил прерывания и коллбэки на события в main_init () и у меня нет цикла основной программы. Процессор занимается своими делами.
Правда, пришлось подрихтовать свою парадигму программирования, и отслеживать развитие событий в разных частях программы.
Спасибо за полезную информацию.
Нашел ваш проект на GitHub GitHub - Intelligent-Productions/UDP_SPI_project: Description registers ESP8266 in ST style. Буду сидеть разбираться.

Необычный метод написания программы для микроконтроллера - без цикла основной программы. Может быть из-за небольшого опыта, но с подобным стилем программирования под микроконтроллеры я ещё не сталкивался.
 
Сверху Снизу