Почему я всегда рассматриваю while(serial.available() > 0) как стандартный способ чтения последовательных данных?
В онлайн-примерах всегда показан этот код для чтения байтов из последовательного интерфейса:
while(serial.available() > 0)
{
char receivedByte = serial.read();
}
Но я не понимаю, почему это работает.
Операция read() «удаляет» один байт из очереди, поэтому цикл while должен использовать все байты из очереди.
Однако что гарантирует, что входящие байты будут помещены в очередь быстрее, чем процесс-потребитель? Я предполагаю, что любая плата Arduino на порядок быстрее, чем стандартная последовательная передача, поэтому она будет истощать очередь и эффективно выходить из цикла while, даже если требуется обработать больше входящих байтов. Что мне здесь не хватает?
2 ответа
Лучший ответ:
Что гарантирует, что входящие байты помещаются в очередь быстрее, чем процесс-потребитель?
Ничего. В коде, обрабатывающем передаваемые данные, это необходимо учитывать. Тот факт, что последовательная передача не так быстра, как выполняется код, не имеет значения, если вы регулярно проверяете выполнение этого цикла while еще раз (например, на каждой итерации неблокирующего loop()
). ). Код не должен полагаться на получение полного сообщения внутри цикла while. Данные обычно сохраняются в собственный буфер и обрабатываются только тогда, когда там находится полное допустимое сообщение (что можно проверить, используя байт-разделитель в конце каждого сообщения). Так что это имеет больше смысла в контексте остальной части соответствующего последовательного кода.
Хотя всегда следует иметь в виду, что в Интернете существует множество кодов для Arduino, и многие из них не так уж хороши.
Это тот ответ, на который я надеялся. Некоторые небрежные реализации используют небольшую задержку(x); внутри цикла, чтобы гарантировать присутствие хотя бы 1 нового байта при повторной проверке условия while. x зависит от скорости передачи данных. Чтение по частям в основном цикле() имеет смысл, но тогда необходимо гарантировать, что общее время выполнения цикла() не превышает время, необходимое для заполнения последовательной очереди, иначе байты будут потеряны. Не так ли?, @Gianluca Ghettini
Да, в этом случае loop()
должен быть неблокирующим. Хотя в любом случае это рекомендуется, потому что это позволяет вам выполнять несколько дел одновременно, в основном выполнять несколько задач и сохранять оперативность реагирования., @chrisl
Примеры в Интернете всегда показывают этот код...
while(serial.available() > 0) { char receivedByte = serial.read(); }
Вы бы не увидели это «всегда»; потому что это Serial
, а не serial
.
Кроме того, опубликованный вами код будет бесполезен, поскольку он будет неоднократно считывать один и тот же байт и ничего с ним не делать.
Предполагая, что вы получаете некоторую лицензию на то, что вы на самом деле видели, было бы лучше, чтобы код постепенно заполнял буфер (и проверял на переполнение), а затем, когда появляется новая строка или другой разделитель, что-то с ним делал .
Вы правы, говоря, что вы, вообще говоря, читаете быстрее, чем поступают данные. Вы также правы в том, что вводить задержки — это глупый способ допустить это.
У меня есть ответ на этом сайте плюс страница с предлагаемыми код, который более подробно описан.
Эти сообщения могут помочь.
- Отправка последовательных данных в прерывании
- Почему люди используют 115200 вместо 9600?
- Ошибка 'Serial' was not declared in this scope
- Как получить ненулевой выход из HX711 и ячейки загрузки?
- Serial.availableForWrite против Serial.flush
- Разделенный последовательный поток Arduino, разделенный запятыми
- Как остановить серводвигатель в текущем положении при использовании последовательного порта? Я хочу, чтобы он оставался в одном положении при получении «0».
- Arduino Serial.ReadString() проблема
Ты прав. Это зависит от того, что еще делается в блоке while. Кстати:
byte
— это тип данных в среде Arduino, лучше не используйте его в качестве имени переменной., @DataFiddler@DataFiddler исправлено, @Gianluca Ghettini
блок if имел бы больше смысла, чем блок while, @jsotola