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)> решило эту проблему. Кто-нибудь знает, почему это так?

, 👍2

Обсуждение

Включите уровень предупреждения в "Файл/Настройки в отношении" в то время как(серийно.доступно) " без " ()", как в". доступно()., @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


2 ответа


Лучший ответ:

4

Я понял, почему while(Serial.available()>0)> и if(Serial.available() > 0)> будут или НЕ будут работать с точки зрения моего кода сдвигового регистра. Это связано с настройкой подачи строки последовательного монитора и возврата каретки! Если он не установлен в значение без конца строки, он либо не зарегистрирует входной номер, либо сбросит его обратно в ноль сразу после считывания ввода. Научился всегда проверять опцию возврата строки в последовательном мониторе! С этим решением исходный вопрос является не более чем общим утверждением if vs while; которое я уже знаю ответ.

Спасибо всем, кто внес свой вклад в этот вопрос! Это действительно помогло мне гораздо больше понять Serial.available() в целом. @jsotola дал действительно хорошую статью. В сочетании с этим видео на YouTubeтеперь оно имеет гораздо больше смысла.

,

0

Некоторые реализации ядра Arduino имеют функции, которые требуют регулярного выхода loop (). Хотя он не часто используется, serialEvent() является примером одной из таких вещей, по крайней мере, в ядре AVR Arduino.

Ядро Arduino ESP8266, помимо всего прочего, выполняет некоторое планирование задач при выходе из функции loop ().

Для вашего конкретного случая использования это может вообще не иметь никакого значения, а скорее всего, и не имеет. Он может даже не генерировать другой код после компиляции. Если вы делаете что-то такое , где не можете позволить себе выйти из loop (), запустить другие вещи и снова войти в loop (), чтобы запустить свой код для второго прохода, то может быть причина производительности использовать свой собственный цикл while внутри loop(). В вашем коде, как он есть в настоящее время, возможная блокировка последовательной записи в конечном итоге ограничит выполнение до той же скорости.

,

Я немного запутался здесь. Таким образом, вы говорите, что существует вероятность выхода/завершения функции " цикл ()", и это может нарушить код, если использовать " если(серийный.доступен ())"?, @Kuan

Я не уверен, что понимаю ваш вопрос, и, похоже, я бы понял, если бы ответ на него был чем-то иным, кроме "нет, я не это имел в виду". Поскольку замена "в то время как" в вашем коде на "если" приводит к более частому выходу " цикла ()", так как в этом разница, и вы спросили " На каких условиях вы бы предпочли одно другому?", вот к чему я обратился. Это лучшая интерпретация вашего вопроса, которую я смог придумать., @timemage

Ладно, теперь я все понял. Мне кажется, что операторы if ведут себя не так, как я ожидал бы, когда они сопряжены с Serial.available(). Он может выйти преждевременно., @Kuan