Пользовательская функция, такая как yield
Насколько я понимаю, yield() используется, когда у вас длинный код (например, цикл), чтобы фоновая обработка, требуемая esp8266, не приостанавливалась на долгое время.
У меня есть приложение, в котором звук должен воспроизводиться постоянно, и одновременно программа должна выполнять другие действия, которые могут включать длинные циклы (которые я внутри них вызываю с помощью yield()). Эти длинные циклы приводят к прерыванию звука.
Какой наилучший идиоматический способ имитировать функцию yield() в моей программе? Поэтому я делаю что-то вроде этого:
for(int i=0;i<10000;++i){
yield();
customeYield();
someFunction(i);
}
Где customeYield() содержит необходимые инструкции для воспроизведения звука. Вот как это выглядит (я использую ESP8266Audio):
if (mp3_->isRunning()) {
if (!mp3_->loop()) {
mp3_->stop();
return true;
}
return false;
}
return true;
Конечно, я могу просто назвать его так, как я это сделал (сделав его глобальным или что-то в этом роде). Однако мне было интересно, есть ли стандартный способ для такой задачи.
@Humam Helfawi, 👍1
Обсуждение1 ответ
Лучший ответ:
Без подсказки, что именно вы делаете в своих длинных циклах, сложно сказать, какой способ будет оптимальным в вашем случае. Не думаю, что есть стандартный способ, но, по сути, существует всего два способа реализовать многозадачность на микроконтроллере:
- Управление прерыванием: можно установить прерывание по таймеру, которое будет срабатывать регулярно для вызова функции
AudioGenerator::loop()(которая заполняет буфер следующими данными). - Неблокирующий код: Используя неблокирующий код, вы можете сначала выполнить одно действие, а затем другое последовательно, настолько быстро, что оба кода будут выполняться достаточно часто. Именно для этого и предназначена используемая вами библиотека (согласно файлу README).
Если вы используете более одного такого длинного цикла в своей функции loop(), вы можете рассмотреть возможность использования конечного автомата (FSM), чтобы вам не приходилось каждый раз добавлять функцию AudioGenerator::loop() в свои длинные циклы, а нужно добавлять ее только один раз для обычной функции loop().
Большое спасибо за ответ. Вообще-то да, я использую FSM. Однако я не совсем понял, как это изменит ситуацию? В конце концов, если какая-то основная функция состояния содержит длинный цикл, она всё равно приостановит выполнение остального кода. Я что-то пропустил?, @Humam Helfawi
Конечный автомат поможет вам разбить длинные циклы на небольшие части, чтобы одно выполнение основной функции loop() не занимало много времени. Затем вы выполняете AudioGenerator::loop() в каждом цикле основной функции loop(). Таким образом, вы немного приостанавливаете длинный цикл для выполнения фоновой задачи (в данном случае: воспроизведения звука) между ними. Это всего лишь стиль кодирования. То, как именно разбить длинные циклы на небольшие части, зависит от кода внутри них. Надеюсь, теперь стало понятнее., @chrisl
А, ладно! Теперь понял... Я думал, что у шаблона есть встроенная поддержка. Реализую по вашему совету, и, кажется, работает... Большое спасибо!, @Humam Helfawi
- Как читать и записывать EEPROM в ESP8266
- Как сделать выводы Tx и Rx на ESP-8266-01 в выводах GPIO?
- Как навсегда изменить скорость передачи данных ESP8266 (12e)?
- Как заставить 5-вольтовое реле работать с NodeMCU
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
- ESP8266 не подключается к Wi-Fi
- esp8266 не отвечает на AT-команды
- Разница между этими двумя платами NodeMCU?
yield() должен быть вызван через определенный промежуток времени, иначе сторожевой таймер перезапустит esp8266. Вы должны вызвать свою функцию, иначе музыка остановится. Никакой магии. yield() делает то, что нужно, и возвращается., @Juraj