Главная chevron_right Функции chevron_right Связь chevron_right Serial.readBytesUntil()

Serial.readBytesUntil()

Serial.readBytesUntil() читает байты из последовательного буфера в массив, останавливаясь на символе-терминаторе, по таймауту или при достижении length байт — сам терминатор в buffer не попадает.

Полная статья

Описание

Serial.readBytesUntil() читает байты из последовательного буфера и складывает их в массив. Чтение прекращается при выполнении одного из трёх условий — именно в таком порядке:

  1. Прочитано заданное количество байт (length).
  2. Истёк таймаут (см. Serial.setTimeout()).
  3. В потоке обнаружен символ-терминатор.

Важно: сам терминатор в возвращаемый buffer не попадает, но при этом извлекается из последовательного буфера — то есть следующий вызов чтения его уже не увидит.

Serial.readBytesUntil() наследуется от класса Stream.

Синтаксис

Serial.readBytesUntil(character, buffer, length)

Параметры

  • Serial — объект последовательного порта. Список доступных портов для каждой платы смотрите на странице Serial.
  • character — символ, при обнаружении которого чтение останавливается. Допустимый тип данных: char.
  • buffer — массив, куда будут записаны прочитанные байты. Допустимые типы данных: массив char или byte.
  • length — максимальное количество байт для чтения. Допустимый тип данных: int.

Возвращает

Количество байт, реально записанных в buffer. Тип данных: size_t.

Функция вернёт 0 в трёх ситуациях:

  • параметр length меньше или равен нулю;
  • таймаут истёк раньше, чем поступил хоть один байт;
  • символ-терминатор был обнаружен сразу, до любых других данных.

Пример кода

Следующий скетч читает данные из последовательного порта до появления заданного символа-терминатора, сохраняет их в буфере и выводит обратно в монитор порта:

char message[20];  // Буфер для хранения сообщения

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("Type a message (end with Enter):");
}

void loop() {
  if (Serial.available()) {
    int bytesRead = Serial.readBytesUntil('\n', message, sizeof(message) - 1);
    message[bytesRead] = '\0';  // Завершаем строку нулевым символом

    Serial.print("You said: ");
    Serial.println(message);
  }
}

Примечания и предупреждения

Символ-терминатор удаляется из последовательного буфера, если количество фактически прочитанных символов не равно length. Это означает, что если чтение остановилось именно по терминатору, а не по достижению length или таймауту, следующий вызов чтения начнётся уже с байта, идущего после терминатора.

Где применяется

  • Разбор текстовых команд. Устройство принимает строки вида "LED_ON\n" — функция читает до символа \n и возвращает готовую команду без лишних символов.
  • Протоколы с разделителями. Если данные передаются через запятую или точку с запятой, readBytesUntil() позволяет разбирать поток поле за полем.
  • Взаимодействие с модулями по UART. Многие GPS- и GSM-модули завершают ответы символом \r или \n — функция естественно вписывается в такую логику.

Практические замечания

  • Функция блокирующая: скетч ждёт данных, пока не выполнится одно из условий завершения. Если данные не приходят, выполнение зависнет на время таймаута.
  • Таймаут по умолчанию — 1000 мс. Изменить его можно через Serial.setTimeout() до вызова readBytesUntil().
  • Убедитесь, что размер массива buffer не меньше length, иначе возможен выход за границы памяти.
  • Функция не добавляет нулевой терминатор '\0' в конец массива. Если нужно работать со строкой через стандартные функции C, добавьте его вручную: buf[n] = '\0';, где n — возвращённое значение.
  • Если функция вернула 0, проверьте: не истёк ли таймаут раньше времени, правильно ли задан символ-терминатор и действительно ли данные поступают в порт.

Полезные материалы