Очищается ли содержимое буфера порта после операции Serial.read()?
- Войдите на сайт для отправки комментариев
Ср, 13/11/2019 - 09:07
Почему-то не нашел информации. Воспроc связан с будущей конфигурацией цикла While (по условию наличия или отсутствия строчки в порте).
Поправил название темы, если Вы не против.
Ответ - да, очищается. Почему-то не нашли информации )).
функция читает один байт, соответственно этот байт и очищается из буфера.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
это вопрос терминологии :) При чтении байта методом read() указатель сдвигается на следующий байт и уменьшается счетчик оставшихся байтов, после вычитывания последнего счетчик становится равным нулю и в этом смысле можно считать. что буфер очищен.
а то что в ячейках буфера остаются ненулевые значения - так это просто свойство буфера...
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
это вопрос терминологии :) При чтении байта методом read() указатель сдвигается на следующий байт и уменьшается счетчик оставшихся байтов, после вычитывания последнего счетчик становится равным нулю и в этом смысле можно считать. что буфер очищен.
а то что в ячейках буфера остаются ненулевые значения - так это просто свойство буфера...
Ну так, значить, формально, буфер не очищается (не забивается нулями). :)
Хрен знает, что имел ввиду ТС, у него на аватарке не написано
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
а что значить очистить буфер (читай байт)? Уничтожить байт? или записать туда FF или 00? но это ведь тоже информация. Понятное дело - речь идёт про то, что программа указывает, что здесь теперь у нас пусто.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Интересно, чем нулевые значения "чище" любых других? Сегрегацией и ксенофобией попахивает.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Интересно, чем нулевые значения "чище" любых других? Сегрегацией и ксенофобией попахивает.
в продолжение темы ... это типа если место можно занять, значит оно свободно и попробуйте оспорить. :)))))
Ладно, признаю, я неправ. Очищается. Пашутить уже нельзя, сразу в сегрегацыи обвиняють. :) Ироды.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Интересно, чем нулевые значения "чище" любых других? Сегрегацией и ксенофобией попахивает.
в продолжение темы ... это типа если место можно занять, значит оно свободно и попробуйте оспорить. :)))))
а пожалуйста: циклический буфер - он одновременно и свободен и занят, причем весь.
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Интересно, чем нулевые значения "чище" любых других? Сегрегацией и ксенофобией попахивает.
в продолжение темы ... это типа если место можно занять, значит оно свободно и попробуйте оспорить. :)))))
а пожалуйста: циклический буфер - он одновременно и свободен и занят, причем весь.
Зачетно!!!! :)))))))))))))))) Видишь суслика? а он есть
Если в буфер положить строку, то содержащаяся в этой строке информация останется в буфере после считывания. Это я имел в виду что не очищается. Очистить буфер от информации - затереть чем угодно - хоть ноликами, хоть единицами хоть белым шумом. А вдруг там пароль от счета на Багамах? Сдвинуть указатель это действие только для обслуживающего буфер драйвера очистка.
Ноль - это тоже данные... Надо как-то вакуумировать или хлорировать ячейки памяти для полной очистки.
Подключить пины, допустим, порта В на + питания, затем:
Должно помочь, зуб даю!
А вдруг там пароль от счета на Багамах?
А вдруг наоборот, его там не было, а в "белом шуме" случайно сгенерится?
Первый вопрос, которым следовало бы задаться, а что, собственно, ТС подразумевает под "очисткой буфера".
Может, имеется в виду, что после "очистки" указанные адреса памяти становятся недоступными как для чтения, так и для записи.
а пожалуйста: циклический буфер - он одновременно и свободен и занят
Прямо буфер Шрёдингера :)
Ничего там не очищается. Если читать весь буфер, то там всегда есть значения отличные от нуля.
Интересно, чем нулевые значения "чище" любых других? Сегрегацией и ксенофобией попахивает.
предлагаю внести предложение и переделать библиотеку чтобы записывать последовательность из F6, как при форматировании
я думаю b707 #4 правильно понял ТС.
я думаю b707 #4 правильно понял ТС.
А я думаю, что это пофиг, т.к. ТС на тему забил и уж двое суток народ сам резвится, без него :)
Простите, друзья, Интернет не вовремя отрубили... Суть вопроса чуть поподробнее. ПК выбрасывает строчку в порт 1 раз в секунду. С ПК подаю в порт некую строчку с параметрами, Ардуина ее читает, парсирует и циклически выполняет программу на основании этих параметров. Отсюда вопрос: Ардуино прочитала порт, и порт опустел? Тогда можно в начале лупа коротким циклом While просто проверять Serial.avalable () на наличие чего-то в порту, и если есть - выполнять программу с новыми параметрами, а если нет - продолжать это делать со старыми. Если в порту после чтения что-то остается, то тогда цикл While надо начинать в начале лупа. а заканчивать в конце. Вот как-то так....
Тогда можно в начале лупа коротким циклом While просто проверять Serial.avalable () на наличие чего-то в порту, и если есть - выполнять программу с новыми параметрами, а если нет - продолжать это делать со старыми.
и не только в начале лупа, можно проверять много раз и выполнять как захотите и прерывание можно сделать, если данные обновились. Главное проверять, собственно счетчик и покажет, что он не пустой если данные пришли новые.
как бы все есть в примере (коротко и мало понятно)
UPD
все не читал, но вроде понятно написано - serialEvent, смутно понимаю, что именно это вы искали или я ошибся?
Ага, спасибо. Правда, про ссылкам не то, что меня интересовало (с парсингом строки я уже разобрался), но все равно спасибо. Что касается вашего текста - все понял, буду действовать..
Простите, друзья, Интернет не вовремя отрубили... Суть вопроса чуть поподробнее. ПК выбрасывает строчку в порт 1 раз в секунду. С ПК подаю в порт некую строчку с параметрами, Ардуина ее читает, парсирует и циклически выполняет программу на основании этих параметров. Отсюда вопрос: Ардуино прочитала порт, и порт опустел? Тогда можно в начале лупа коротким циклом While просто проверять Serial.avalable () на наличие чего-то в порту, и если есть - выполнять программу с новыми параметрами, а если нет - продолжать это делать со старыми. Если в порту после чтения что-то остается, то тогда цикл While надо начинать в начале лупа. а заканчивать в конце. Вот как-то так....
1. Да, в Вашей терминологии порт после чтения становится пустым.
2. Делать что-либо в начале "лупа" или в конце - нет никакой разницы.
3. Идея с проверкой available - плохая: контроллер работает намного быстрее собственного порта, поэтому почти наверняка проверка available произойдет тогда, когда порт еще не принял строку до конца. Правильный алгоритм - парсить не принятую строку, а входной поток посимвольно, и как только будет принят признак конца строки (а не начала, как Вы предполагаете), переключаться на новые параметры.
Благодарю, мысль понял. Но в моем случае входящая строка будет строго определенной длины, поэтому (на мой взгляд!) проще проверять именно это плюс некий значок ее начала (или окончания), а не посимвольно формировать ее из потока. Посимвольный прием, конечно, более универсален, но в конкретной задаче излишен. Нет?
Нет, т к не факт что вся ваша строка придёт сразу а не через 0.05 секунды например, соответственно если жёстко ждать конца строки то за эту долю секунды скетч будет простаивать, что нехорошо
Спасибо, эта мысль тоже понятна. Но в моей задаче такое простаивание скетча не критично.
Спасибо, эта мысль тоже понятна. Но в моей задаче такое простаивание скетча не критично.
Да я думаю сложно найти задачу, где это простаивание оказалось критичным. Войну и мир если только по сериалу передаватьс, но таким я ещё не занимался.
Поэтому я тоже в своих скетчах проверяю сериал.аваилибл.
Ну например... Опрос кнопок. Если процессор будет где-то простаивать то разумеется опроса не будет. Да и простаивание где-то процессора в конкретном месте уже не красит программу и программиста написавшего этот шедевр.
Я не совсем понял, т.е. предлагается после каждого принятого байта переключать МК на другие задачи? А эти самые регулярные переключения не скажутся в итоге на скорости обмена?
это если интервалы короткие. А если программу-передатчик на другой стороне линии тоже писал программист. для которого "простаивание не критично" - там дегко могут быть задержки уже не в сотые доли секунды, а в разы больше...
не после каждого байта, а после выборки всех байт из буфера Сериал. На скорости Сериал обычно это не сказывается - последовательный интерфейс один из самых медленных в контроллере, как правило это он все тормозит. а не наоборот
это если интервалы короткие. А если программу-передатчик на другой стороне линии тоже писал программист. для которого "простаивание не критично" - там дегко могут быть задержки уже не в сотые доли секунды, а в разы больше...
А там какие задержки? Serial.print(...) разве с задержкой работает?
да
http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-nim-svyazano?page=1#comment-439631
Update: Хотя нет, там цикл пока весь UART не вычитается, но все равно обработка идет каждого байта.
UART в арудино устроен на прерываниях. После приема и отправки каждого байта мк переключается на обработку, а затем возвращается к предыдущей задаче, и никто этого даже не замечает.
Вы не путайте print() и read().
Первый, если посылка меньше буфера, может отпустить камень еще до того, как начался первый байт передачи, и продолжать передачу на фоне, пока камень занимается другими делами.
А второй может вычитать из буфера только то, что там уже успело накопиться. По available() мы узнаем о приходе 1-го байта, т.е. либо мы считываем только первый байт посылки, либо ждем, пока не накопятся остальные. А накапливаются они очень медленно.
Впрочем, если использовать available() не для проверки наличия "чего-то", а для проверки, что накопилось уже нужное количество байтов, - такой вариант опроса не будет отнимать лишнего времени.
Вы не путайте print() и read().
Первый, если посылка меньше буфера, может отпустить камень еще до того, как начался первый байт передачи, и продолжать передачу на фоне, пока камень занимается другими делами.
А второй может вычитать из буфера только то, что там уже успело накопиться. По available() мы узнаем о приходе 1-го байта, т.е. либо мы считываем только первый байт посылки, либо ждем, пока не накопятся остальные. А накапливаются они очень медленно.
Впрочем, если использовать available() не для проверки наличия "чего-то", а для проверки, что накопилось уже нужное количество байтов, - такой вариант опроса не будет отнимать лишнего времени.
Я не путаю. B707 высказался что на передающей стороне могут быть задержки.
Serial.Available() в моем случае не имеет альтернативы, т.к. у меня там есть блокирующие функции в которые приходится внедрять такие конструкции, чтобы выйти из них.
Я посмотрел код функции available, в ней нет ничего, что могло бы замедлять работу МК, т.к. чтение в ней происходит не каких-либо регистров, а непосредственно глобальных переменных, что совсем не плохо.
имхо, по-нормальному нужно, чтобы в пакете, кроме данных содержались также маркер начала, длина пакета и контрольная сумма, тогда собирать на приёмной стороне такой пакет легко и надёжность выше. И читаем по байту за проход лупа (если конечно этот байт уже в буфере появился, если нет - проходим мимо) и никаких задержек.
Нет, ну по идее, чтобы без задержек, да при фиксированной длине пакета - получается два варианта:
1. На каждом проходе loop() Опрашиваем по available() [!=0], и складываем в буфер или сразу посимвольно парсим пока не придет все сообщение. (универсальный способ, допустим при неизвестной заранее длине пакета)
2. Крутя цикл loop(), дожидаемся, пока станет available() == N, где N - длина пакета, и тогда читаем целиком.
А задержка может возникать тогда, когда мы начинаем читать по первому пришедшему байту и не отпускаем процедуру чтения, пока не придет последний пакет.
имхо, по-нормальному нужно, чтобы в пакете, кроме данных содержались также маркер начала, длина пакета и контрольная сумма, тогда собирать на приёмной стороне такой пакет легко и надёжность выше. И читаем по байту за проход лупа (если конечно этот байт уже в буфере появился, если нет - проходим мимо) и никаких задержек.
Ещё нужно число передавать не символьным знаком типа *char.
А я помню стандарт RsS232 предусматривал два дополнительных провода. Один для выставления логического уровня когда отправляются данные, другой читают когда принимаются. Можно нечто подобное и тут сделать для ускорения работы, но похоже тут в большинстве случаев это лишнее.
Нет, ну по идее, чтобы без задержек, да при фиксированной длине пакета - получается два варианта:
1. На каждом проходе loop() Опрашиваем по available() [!=0], и складываем в буфер или сразу посимвольно парсим пока не придет все сообщение. (универсальный способ, допустим при неизвестной заранее длине пакета)
2. Крутя цикл loop(), дожидаемся, пока станет available() == N, где N - длина пакета, и тогда читаем целиком.
я всегда работаю только по первому варианту - при каждом обороте ЛУП читаю available() и выбираю из буфера все имеющиеся символы. Если сообщение не пришло целиком - без ожидания перехожу к другим ветвям программы
Если пришла какая нибудь html страница по gprs, она в принципе не влезет в память МК, так что парсить online единственный универсальный способ.
я всегда работаю только по первому варианту...
Это если не нужен лексический разбор. Если нужен, то проще читать по одному символу (следующий при следующем проходе прочитается), т.к. лексические автоматы работают с одним символом и тот, возможно, придётся вернуть в поток.
я всегда работаю только по первому варианту...
Токо по первому. С поправкой на "складываем в буфер или сразу посимвольно парсим" - там как правило и то и другое делается. Ну распарсили очередной символ и пришли к выводу что это не все символы идентификатора или значения и что делать? Только сохранять уже принятое в буфере пока следующий символ не приехал. Живой пример здесь http://arduino.ru/forum/apparatnye-voprosy/gsm-modem-a6-v-rezhime-tcp , строки 714-717.
Одна беда. Парсинг "на лету" - самый сложный из других подходов.
ПС. При неизвестной заранее длине пакета таки бывают варианты. Эту неизвестную заранее длину передают (явно или неявно) гдето в начале пакета чем сводят дальнейшую работу к случаю известной длинны.
По теме топика. Определимся что имеет ввиду ТС как буффер. Если просто массив - read() не меняет его содержимое. Правильней считать буфером не только сам массив, но и набор переменных связанных с ним для организации буфера. В таком случае вызов read() при наличии принятых данных загрязняет буфер, т.к. уменьшает на 1 байт кол-во данных в нем и увеличивает на 1 байт количество временно не использованных ячеек - т.е. мусора.
Скорее ТС включил валенок. Но есть канальный уровень а есть транспортный. И там и там цель передача и получение данных. Но если канальный ЭТОSPI I2C ONEWIRE, то транспортный это Serial. Что понятнее, канальный это такси сел и едешь. То транспортный это пришёл на почту и отправил посылку, или получил если дошла. Канальный это дорогой и надо выделять время, то почта дешевле и можно в удобное время отправить-получить. Теперь вопрос. Можно очистить почту. Можно но до следующего привоз. А привоз он следует своей логике и от воли клиентов не зависит.
Даже и не думал, что простой с первого взгляда вопрос вызовет столь широкую дискуссию :)
Тогда так. В порт от ПК один раз в секунду приходит 27-символьная строка с параметрами. Ардуино ее читает, анализирует (парсинг) и рассовывает параметры по переменным. После чего начинает выполнять очередной луп согласно изменившимся или не изменившимся переменным. Только и всего. Отсюда вопрос и возник. Если порт очищается - то его достаточно прочесть в начале лупа, выявить, соответствует ли длина строки 27 символам, если да, то закрыть цикл While и работать с новыми параметрами, если нет - то игнорировать и делать все как раньше.
Ага, а на 13 символе прилетит помеха и/или delay, или прерывание на вывод параметров в serial сработает, параметр прочитается криво, железка угробит что нибудь более серьёзное.
Если порт очищается - то его достаточно прочесть в начале лупа, выявить, соответствует ли длина строки 27 символам, если да, то закрыть цикл While и работать с новыми параметрами, если нет - то игнорировать и делать все как раньше.
Вы сами-то поняли, что тут написано? Я нет. Потому и срач на неделю, что все пытаются угадать что же Вам надо и спорят между собой.
если да, то закрыть цикл While и работать
Какой ещё цикл while?
если нет - то игнорировать и делать все как раньше.
Что "всё как раньше"?
Т.е. Вам надо примерно так:
Входите в луп, смотрите сколько символов пришло. Допустим прийти успело 26 (один ещё не успел). Поскольку их не 27, Вы выбрасываете их и "делаете всё как раньше". При следующем лупе приходит не успевший в прошлый раз 27-ой символ. Поскольку символов опять не 27, а один, Вы и его выбрасываете и "делаете всё как раньше".
Правильно, Вам так надо? Если так, то проще забить и вообще эти символы не получать.