Использование 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
@Thomas Weller, 👍1
1 ответ
Лучший ответ:
Это связано с тем, что выходные данные серийного номера буферизуются. Он по-прежнему отправляет первый бит данных, пока вы меняете скорость передачи данных, и с тех пор это просто полный беспорядок.
Вам нужно принудительно завершить отправку, прежде чем вы сможете изменить скорость передачи с помощью 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();
}
Это будет ждать после каждой печати, пока все данные не будут отправлены "по сети", прежде чем изменить скорость передачи данных для следующей печати.
- Float печатается только 2 десятичных знака после запятой
- Как получить правильный последовательный порт?
- Как отобразить всю входящую строку с serial monitor в arduino ide?
- SoftwareSerial данные недоступны
- Servo_Pointer' was not declared in this scope
- Использование ESP8266 с Arduino Uno - не удается заставить AT-команду работать
- Операторы If/Else на Arduino не выполняются
- Управлять 2 сервоприводами с последовательным считыванием
Не лучше ли использовать
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