Serial.readBytesUntil()
Serial.readBytesUntil() читает байты из последовательного буфера в массив, останавливаясь на символе-терминаторе, по таймауту или при достижении length байт — сам терминатор в buffer не попадает.
Полная статья
Описание
Serial.readBytesUntil() читает байты из последовательного буфера и складывает их в массив. Чтение прекращается при выполнении одного из трёх условий — именно в таком порядке:
- Прочитано заданное количество байт (
length). - Истёк таймаут (см. Serial.setTimeout()).
- В потоке обнаружен символ-терминатор.
Важно: сам терминатор в возвращаемый 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, проверьте: не истёк ли таймаут раньше времени, правильно ли задан символ-терминатор и действительно ли данные поступают в порт.