if(Serial.available()>0) VS while(Serial.available()>0)
Какова разница на низком уровне между if(Serial.available() > 0)>
и while(Serial.available() > 0)>
? На каких условиях вы бы предпочли одно другому?
Я тестировал свои коды на 4 последовательных сдвиговых регистрах 74HC595, управляющих несколькими светодиодами. Код принимает номер от последовательного монитора и отображает его в двоичном виде через светодиоды. Вот код ниже, который работал:
#define latchPin 8 //ST_CP pin of 74HC595
#define clockPin 9 //SH_CP pin of 74HC595
#define dataPin 7 //DS pin of 74HC595
//number of 74HC595 in daisy chain
#define numOfDaisyChainReg 4
byte registerVal[numOfDaisyChainReg];
void setup() {
Serial.begin(115200);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
while (Serial.available() > 0) {
uint32_t num = Serial.parseInt();
Serial.print(num, DEC);
Serial.print(" : ");
Serial.println(num, BIN);
//breaks the recieved int into 4 unsigned bytes
//and assigns the byte value into the "registerVal" array
for (uint8_t a = 0; a < numOfDaisyChainReg; a++) {
registerVal[a] = (num >> (numOfDaisyChainReg - (a + 1)) * 8) & 0xFF;
Serial.print("registerVal["); Serial.print(a); Serial.print("] = ");
Serial.println(registerVal[a], BIN);
}
//writes the 4 bytes into the shift register
digitalWrite(latchPin, LOW);
for (uint8_t x = 0; x < numOfDaisyChainReg; x++) {
shiftOut(dataPin, clockPin, MSBFIRST, registerVal[x]);
}
digitalWrite(latchPin, HIGH);
}
}
Первоначально у меня был if(Serial.available() > 0)>
, и это не сработало, так как не загорелись светодиоды, несмотря на то, что все остальное в коде работало так, как ожидалось. Переключение на while(Serial.available() > 0)>
решило эту проблему. Кто-нибудь знает, почему это так?
@Kuan, 👍2
Обсуждение2 ответа
Лучший ответ:
Я понял, почему while(Serial.available()>0)>
и if(Serial.available() > 0)>
будут или НЕ будут работать с точки зрения моего кода сдвигового регистра. Это связано с настройкой подачи строки последовательного монитора и возврата каретки! Если он не установлен в значение без конца строки, он либо не зарегистрирует входной номер, либо сбросит его обратно в ноль сразу после считывания ввода. Научился всегда проверять опцию возврата строки в последовательном мониторе! С этим решением исходный вопрос является не более чем общим утверждением if
vs while; которое я уже знаю ответ.
Спасибо всем, кто внес свой вклад в этот вопрос! Это действительно помогло мне гораздо больше понять Serial.available()
в целом. @jsotola дал действительно хорошую статью. В сочетании с этим видео на YouTubeтеперь оно имеет гораздо больше смысла.
Некоторые реализации ядра Arduino имеют функции, которые требуют регулярного выхода loop ()
. Хотя он не часто используется, serialEvent()
является примером одной из таких вещей, по крайней мере, в ядре AVR Arduino.
Ядро Arduino ESP8266, помимо всего прочего, выполняет некоторое планирование задач при выходе из функции loop ()
.
Для вашего конкретного случая использования это может вообще не иметь никакого значения, а скорее всего, и не имеет. Он может даже не генерировать другой код после компиляции. Если вы делаете что-то такое , где не можете позволить себе выйти из loop ()
, запустить другие вещи и снова войти в loop ()
, чтобы запустить свой код для второго прохода, то может быть причина производительности использовать свой собственный цикл while внутри loop()
. В вашем коде, как он есть в настоящее время, возможная блокировка последовательной
записи в конечном итоге ограничит выполнение до той же скорости.
Я немного запутался здесь. Таким образом, вы говорите, что существует вероятность выхода/завершения функции " цикл ()", и это может нарушить код, если использовать " если(серийный.доступен ())"?, @Kuan
Я не уверен, что понимаю ваш вопрос, и, похоже, я бы понял, если бы ответ на него был чем-то иным, кроме "нет, я не это имел в виду". Поскольку замена "в то время как" в вашем коде на "если" приводит к более частому выходу " цикла ()", так как в этом разница, и вы спросили " На каких условиях вы бы предпочли одно другому?", вот к чему я обратился. Это лучшая интерпретация вашего вопроса, которую я смог придумать., @timemage
Ладно, теперь я все понял. Мне кажется, что операторы if ведут себя не так, как я ожидал бы, когда они сопряжены с Serial.available(). Он может выйти преждевременно., @Kuan
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- В чем разница между Serial.write и Serial.print? И когда они используются?
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Программы построения последовательных данных
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Очистить существующий массив при получении новой последовательной команды
Включите уровень предупреждения в "Файл/Настройки
в отношении" в то время как(серийно.доступно) " без " ()", как в". доступно()
., @timemage"несмотря на то, что все остальное в коде работает так, как и ожидалось"... это может быть не так, @jsotola
подумайте о раковине, полной грязной посуды .... "если (dirtyDish.доступно > 0) {washDishOrNot ()}", позволяет вам пойти к раковине, может быть, вымыть посуду или несколько, и пойти поиграть ...... "в то время как (dirtyDish.доступно > 0) {washDishOrNot ()}" вы застряли бы в раковине, пока не осталось бы грязной посуды, или пока вы не воспользовались бы аварийным выходом, @jsotola
Я надеюсь, что это просто опечатка, так как ее нет в основном списке, и ответил на ту часть, на которую я мог. А также, что это не просто сводится к тому, чтобы не читать о ["в то время как"] (https://www.arduino.cc/reference/en/language/structure/control-structure/while/) и [
если
](https://www.arduino.cc/reference/en/language/structure/control-structure/if/)., @timemage@timemage возражает, что это была опечатка. В разделе кода он был указан как " Серийный.доступен ()", но забыл добавить "() " за пределами этого. Моя вина. Я все исправлю., @Kuan
@jsotola У меня было предчувствие, что это будет что-то вроде этого. Любопытно, чем заканчивается/прерывается оператор if(Serial.available() > 0). Основываясь на логике кода, я должен закончить цикл for внутри, прежде чем завершится оператор if serial. Завершив цикл for, регистр сдвига должен иметь возможность выводить данные на светодиоды., @Kuan
оператор "если" проверяет наличие данных ... вы можете собрать полученные байты в буфер, если хотите, или вообще ничего не делать ... вы должны проверять каждый байт на наличие значения конца данных ... обычно это символ новой строки `\n" ... когда конец данных получен, вы обрабатываете буфер .... дело в том, что вы могли бы выполнять другие задачи при получении последовательных данных, @jsotola
@jsotola Допустим, если бы я хотел использовать "если(серийный.доступен ()>) "вместо " пока", чтобы arduino выполнял другие задачи, получая введенный мной номер int. Какие строки кода мне нужно добавить, чтобы он работал так, как раньше?, @Kuan
https://majenko.co.uk/blog/reading-serial-arduino, @jsotola
@jsotola. Спасибо! Это было интересное чтение. Я внедрю это в свой код для тестирования :), @Kuan