Serial.peek()
Serial.peek() читает следующий байт из буфера Serial, не удаляя его — в отличие от read(), байт остаётся на месте и будет возвращён снова при следующем вызове.
Полная статья
Описание
Serial.peek() читает следующий байт из буфера последовательного порта, но не удаляет его оттуда. Это принципиальное отличие от read(): после вызова peek() байт остаётся в буфере, и следующий вызов peek() вернёт тот же самый символ. Только read() действительно «съедает» байт и двигает указатель буфера вперёд.
Такое поведение удобно, когда нужно принять решение о дальнейшей обработке данных, не теряя первый символ. Например, можно посмотреть на заголовок пакета и выбрать нужный обработчик, а затем передать весь поток дальше уже через read().
Serial.peek() наследуется от класса Stream.
Синтаксис
Serial.peek()
Параметры
Функция допускает следующий объект:
Serial: объект последовательного порта. См. список доступных последовательных портов для каждой платы на странице Serial.
Возвращает
Первый байт из входящего буфера в виде числа от 0 до 255, или -1, если буфер пуст. Тип данных: int.
Важно помнить, что возвращаемый тип — int, а не byte. Значение -1 используется именно как сигнал об отсутствии данных, поэтому не приводите результат к byte до проверки на -1.
Пример кода
Следующий код заглядывает в буфер и печатает символ, не извлекая его:
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Type something:");
}
void loop() {
if (Serial.available()) {
char nextChar = Serial.peek(); // Смотрим на следующий символ
Serial.print("Next character will be: ");
Serial.println(nextChar);
char actualChar = Serial.read(); // Теперь действительно считываем его
Serial.print("Read character: ");
Serial.println(actualChar);
}
}
Где применяется
- Разбор протоколов с заголовком — проверяете первый байт пакета, чтобы определить его тип, и только потом читаете весь пакет целиком.
- Условное чтение — нужно убедиться, что следующий символ — цифра или буква, прежде чем передавать данные в функцию разбора числа.
- Синхронизация потока — ищете стартовый маркер (
'$','#'и т.п.) без потери байтов: смотрите черезpeek(), и если символ не тот — читаете и выбрасываете его черезread().
Практические замечания
peek()не блокирует выполнение программы: если буфер пуст, функция немедленно вернёт-1.- Перед вызовом
peek()полезно проверитьSerial.available() > 0, чтобы не обрабатывать ложное-1. - Не путайте
-1как «нет данных» с байтом0xFF(255): они различаются именно потому, что возвращаемый типint, а неbyte. - Многократные вызовы
peek()подряд всегда возвращают один и тот же байт — буфер не изменяется. - Если нужно пропустить нежелательный символ, используйте
read()—peek()сам по себе ничего не удаляет.