Использование Serial.begin() дважды

Я обучаю детей программированию Arduino. Мы будем использовать Serial для целей отладки, поэтому мы начали с простой программы HelloWorld. Я позволяю им пробовать разные вещи, включая изменение скорости.

Теперь один из результатов был таким же простым, как

void setup() {
  Serial.begin(115200);
  Serial.println("Hello");
}

void loop() {
  Serial.begin(115200);
  Serial.println("world");
  Serial.begin(9600);
  Serial.println("world");
}

Я ожидал, что Arduino будет работать именно так, как написано, но монитор последовательного порта Arduino IDE немного запутается. Когда монитор настроен на 115200 бод, я ожидал увидеть

Hello
world
_#&%$"    < какая-то фигня
world
_#&%$"    < опять мусор
...

Однако на самом деле выводится только одна строка

H⸮⸮⸮⸮C

Почему? Нельзя ли изменить скорость передачи между ними?

В официальной документации не говорится, что мы можем использовать Serial.begin() только один раз.

Я использую Arduino Uno и Arduino IDE 1.8.9

, 👍1


1 ответ


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

3

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

Вам нужно принудительно завершить отправку, прежде чем вы сможете изменить скорость передачи с помощью Serial.flush():

void setup() {
  Serial.begin(115200);
  Serial.println("Hello");
  Serial.flush();
}

void loop() {
  Serial.begin(115200);
  Serial.println("world");
  Serial.flush();
  Serial.begin(9600);
  Serial.println("world");
  Serial.flush();
}

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

,

Не лучше ли использовать Serial.end() для сброса указателя буфера?, @Peter Paul Kiefer

Почему? Это круговой буфер - нет ни начала, ни конца, чтобы сбросить его., @Majenko

Извините, я имел в виду буфер чтения. ОП, очевидно, учитель. Поскольку он должен объяснять это другим людям, он должен знать, что также возможно и в чем разница. Использование end() не только очищает буфер записи, но и сбрасывает буфер чтения. Это может быть важно, так как переключение скорости имеет смысл только в том случае, если оно согласовано с партнером по общению. Если это происходит асинхронно, в буфере чтения могут быть нежелательные данные. С другой стороны, могут быть ситуации, когда буфер чтения должен быть сохранен, поэтому использование end() также может быть проблемой., @Peter Paul Kiefer

Кстати, круговой буфер имеет указатели на начало и конец. Сброс указателей в этом случае означает установку указателя головы на указатель хвоста, чтобы очистить данные буфера., @Peter Paul Kiefer

Вы предполагаете, что так везде. Эта функциональность недокументирована. Да, ядро Arduino это делает, но нет никаких гарантий, что это делает каждое ядро. Или даже каждая версия ядра Arduino делает это (например, сброс был изменен с очистки буфера чтения на блокировку буфера записи...). Кроме того, отключение и повторное включение последовательного порта может вызвать непреднамеренные побочные эффекты (плавающие контакты), которые могут вызвать проблемы., @Majenko

Функционал задокументирован https://www.arduino.cc/reference/en/language/functions/communication/serial/end/. Ваша последняя фраза заставляет меня задуматься. Вы правы, переключение контактов на обычное использование тоже может вызвать проблемы. Это необходимо учитывать в переговорном процессе. Я думаю, что наша беседа очень информативна. ;-) По крайней мере, у меня есть над чем подумать., @Peter Paul Kiefer

Нет, функция «очистить буфер rx» *не* документирована. *Функция* задокументирована, практически без какой-либо информации, но нигде не говорится об очистке каких-либо буферов или даже о выполнении flush()., @Majenko

Думаю, я бы реализовал Serial.begin() таким образом, чтобы flush() был встроенным. Но ладно... Думаю, официальная документация еще не идеальна., @Thomas Weller

@PeterPaulKiefer: Преимущество преподавания в том, что я всегда узнаю что-то новое. Лично я никогда бы не написал такую программу, потому что мне было ясно, что на выходе будет ерунда. Но эти малыши (от 9 до 12 лет) еще не ограничены в своем опыте. Они делают забавные случайные вещи, иногда с таким неожиданным результатом. И я надеюсь, что будут еще вопросы :-) Наверное, я пока не могу им это объяснить, потому что понятие "буфер" находится далеко за пределами их понимания., @Thomas Weller

Я добавил запрос на изменение официальной документации: https://github.com/arduino/reference-en/issues/711., @Thomas Weller

@ThomasWeller Хотелось бы, чтобы таких как ты было больше. Документация действительно требует много работы..., @Majenko

@ThomasWeller Вы правы, младшие дети и художники — невероятно хороший источник вдохновения. Они не боятся неудач. Они пробуют что-то, даже если думают, что это не сработает. Я считаю, что в этом разница между людьми и компьютерами и почему компьютер может быть творческим. Они предназначены для того, чтобы не делать ошибок. Кстати: если дети действительно заинтересованы в программировании MCU (мне так кажется), они учатся со скоростью света. А вопросы о буферах могут возникнуть быстрее, чем вы думаете ;-), @Peter Paul Kiefer

Маженко Полностью с вами согласен, что документация в худшем состоянии. Мне часто приходится просматривать исходный код, чтобы найти нужную информацию. А документация — кошмар для новичков. Я часто думал о том, чтобы внести свой вклад в документацию после моих исследований. Но я боюсь, что мой плохой английский не понятен, особенно новичкам. Поскольку документация неполная, я не использую ее в качестве справочного материала для своих ответов здесь. «Кодекс — это правда!» Изменения могут происходить как в коде, так и в документах, поэтому не имеет значения, на чем я основывал свои ответы., @Peter Paul Kiefer