Очистка буфера
- Войдите на сайт для отправки комментариев
Пнд, 07/03/2016 - 01:32
Добрый вечер,
Вот код.
int val; void setup() { Serial1.begin(115200); Serial.begin(115200); Serial1.setTimeout(7); } void loop() { if (Serial1.available() > 0) { val = Serial1.parseInt(); // выполняется код Serial.println(val); //Serial1.flush(); - не работает } }
С одного устройсва на плату по Serial1 отправляется значения, на плате выполняется код, и потом отпраляются обратно другие значения на другой Serial порт. Но дело в том,что val принимает только самое первое значение из буфера, получается,что программа работает с запозданием. И выполняет расчеты со всеми значениями из буфера.
Как сделать так,чтобы val посредством parseInt принимал только последнее поступившее значение в буфер?
Интересно а где вы присвоили val новое значение которое он должен передать, например
Идея такова что между приемом и отправкой должна стоять Ваша функция обработки принятой информации. иначе получается что отправляется то что принято. для реализации вашей идеи только путем сравнения. Создаете case или if с перечислением сообщений на которые должна быть реакция.
Дело не в этом.
Во время работы функции обработки принятой информации, на микроконтроллер поступают ещё значения. И даже если в serial порт перестают поступать данные, функция продолжает работу, пока все значения из буфера не обработает.
Пс забыл упомянуть, что мой код - пример, там показана лишь основная часть...
Всё логично с точки зрения встроенных классов: пока буфер приёма не переполнился, и пока в буфере есть что-то, похожее на число - он его вам и будет возвращать. В исходниках Stream parseInt юзает peek, который в HardwareSerial возвращает символ из текущей позиции, никуда позицию чтения не сдвигая, в отличие от вызова read, в котором позиция чтения сдвигается.
Вывод: либо переделывать, либо - после parseInt вычитывать весь буфер вызовами read, пока есть available().
Скачал старую версию IDE, вставил Flush() в код, но все равно функция работает с запозданием. Еще пытался поменять parseint на peek - опять та же история. Уже не знаю, что и делать.
Пробовал завершать прием данных с помощью Serial.end(), опять не помогло:
Или я ни чего не понимаю или суть такова, parsentInt обрабатывает по 2 байта int = byte * 2; следовательно вы считываете только первую посылку. Посмотрел примеры людей в интернете, там это выглядит так:
Следовательно сколько элементов вы передаете, столко раз надо прочитать поток, а значит должно быть столько переменных val n, val n+1. Сколько аргументов вы передаете. Последним будет val end, вот его то и выведя в UART увидите в мониторе последнее принятое значение.
Здесь мы принимаем аргумент за аргументом и при выполнении условия окончания приема выходим с сохранением последнего принятого аргумента, может надо будет попробовать !Flush() для условия while, но это уже ньюансы.
Скачал старую версию IDE, вставил Flush() в код, но все равно функция работает с запозданием. Еще пытался поменять parseint на peek - опять та же история. Уже не знаю, что и делать.
Пробовал завершать прием данных с помощью Serial.end(), опять не помогло:
Вы хотя бы осознаёте, что пытаетесь делать? Читаете документацию - хотя бы? peek - оставляет буфер нетронутым, никак не меняя позицию чтения. Serial.end - вообще из другой оперы.
Я же говорю - для того, чтобы вычитать два числа из Serial вызовами parseInt - надо понимать, как этот самый parseInt устроен. Я писал выше, как. Он не меняет позицию чтения из буфера, пока там есть что-то похожее на число. Поэтому с вашей стороны надо предпринять какие-то действия, чтобы дать понять Serial, что нужное вам число вы прочитали. Выше - я писал вариант.
Для танкистов, ещё раз: в буфер упал символ '1'. Его можно преобразовать в число? Можно. Вызов parseInt вернёт вам единичку в виде уже числа, а не символа, оставив эту единичку в буфере. Далее - в буфер падает символ '2', вы вызываете parseInt и - получаете, как и ожидалось, число 12, потому что и '1', и '2' - можно преобразовать в числа 1 и 2, и их вместе - в число 12.
В каком месте моих объяснений я пишу на китайском?
З.Ы. Строго говоря, внутри parseInt есть вызов read, но - тут возникают проблемы, когда в буфере ещё не всё число. Но про это - не будем, да?
Скачал старую версию IDE, вставил Flush() в код, но все равно функция работает с запозданием. Еще пытался поменять parseint на peek - опять та же история. Уже не знаю, что и делать.
Пробовал завершать прием данных с помощью Serial.end(), опять не помогло:
Вы хотя бы осознаёте, что пытаетесь делать? Читаете документацию - хотя бы? peek - оставляет буфер нетронутым, никак не меняя позицию чтения. Serial.end - вообще из другой оперы.
Я же говорю - для того, чтобы вычитать два числа из Serial вызовами parseInt - надо понимать, как этот самый parseInt устроен. Я писал выше, как. Он не меняет позицию чтения из буфера, пока там есть что-то похожее на число. Поэтому с вашей стороны надо предпринять какие-то действия, чтобы дать понять Serial, что нужное вам число вы прочитали. Выше - я писал вариант.
Для танкистов, ещё раз: в буфер упал символ '1'. Его можно преобразовать в число? Можно. Вызов parseInt вернёт вам единичку в виде уже числа, а не символа, оставив эту единичку в буфере. Далее - в буфер падает символ '2', вы вызываете parseInt и - получаете, как и ожидалось, число 12, потому что и '1', и '2' - можно преобразовать в числа 1 и 2, и их вместе - в число 12.
В каком месте моих объяснений я пишу на китайском?
Дык ЗАПЯТАЯ и является тем самым разделителем что здесь не правильно и не понятно.
Или я ни чего не понимаю или суть такова, parsentInt обрабатывает по 2 байта int = byte * 2; следовательно вы считываете только первую посылку. Посмотрел примеры людей в интернете, там это выглядит так:
Не увидел, где там по два байта:
Читает, пока есть данные в буфере приёма и пока не уткнётся в неподходящий символ.
Я потрудился почитать как все это должно работать, посмотрел как умные люди используют данные функци и попытался как понимаю ему объяснить как это можно примерно реализавать. Может тоже не прав. Хотя вижу это все в первый раз.
Вот лень компилировать и проверять, но навскидку, без всяких parseInt и прочей шелухи. Считаем, что команда окончена, когда идёт символ новой строки:
Делов на три минуты. Числа посылать, разделяя их запятой, например. Или - любым другим символом или строкой, см.
Не увидел, где там по два байта:
Я так понял что эта фунция может скушать максимально 0XFFFF. Т.е. преобразовать полученный аргумент в число от 0 до 65535. Значит значение аргумента должно лежать в этих пределах. Как то так....
В моём коде есть недоработка, лень дописывать, кому надо - увидит.
Не увидел, где там по два байта:
Я так понял что эта фунция может скушать максимально 0XFFFF. Т.е. преобразовать полученный аргумент в число от 0 до 65535. Значит значение аргумента должно лежать в этих пределах. Как то так....
Ей наплевать на переполнение, посмотрите, наконец, кусок кода из исходников! Читает, пока символы есть в буфере, вываливается по таймауту, или когда встретит символ, который нельзя сконвертировать в число. И тупо накапливает число:
ГДЕ тут два байта ограничение?
Холивар прекращаем, господа, достаём огнетушители и яростно поливаемся!
Спасибо большое за ответы.
Почитал документацию...
DIYMan, в вашем коде используется read, а он также берет только самый первый в очереде символ, есть ли аналог read, который мог принимать только последнее поступившее значение из буфера?
По сути ваш код и этот похожи :?
P.s. прошу прощения,если что-то не понял
Спасибо большое за ответы.
Почитал документацию...
DIYMan, в вашем коде используется read, а он также берет только самый первый в очереде символ, есть ли аналог read, который мог принимать только последнее поступившее значение из буфера?
Вызов read меняет позицию чтения из буфера, так что всё будет нормально. Почему лучше не использовать parseInt - я писал выше, на примере того, когда в буфер упала ещё не вся строка, переданная ардуине.
Если после
if
(inChar ==
'\n'
) {
вставить delay(1000);, и отправить на плату большое кол-во значений, то код выше выводит только все прешедшие за паузу значения, а не последнее. Получается, отправил 40 значение, и потом все 40 сек будет их присылать, а не только последнее прешедшее за паузу.
Если Вам нужен только последний символ, ну и вычитывайте всё в никуда, оставляя только последний:
хотите последнее число:
upd: с числом я явно нахомутал :) но надеюсь идея понятна
Спасибо, все понятно
А я для такого очищения буфера дописал ещё одну строчку считывания порта. При этом той переменной нигде не использую и всё заработало. Специально для того что бы понять в чём ошибка даже вывод результата ввода на экран делал. Приэтом если переменную вводить не char а int ошибка усугубляется. Вот код