Serial, нужна консультация

Здравствуйте.

Перадаю вот такую строку: “abcdef”
В мониторе вижу такую картинку:

stsim=1
stsim=2
stsim=3
stsim=4
stsim=5
stsim=6
stsim=7

Почему выводится семь строчек, а не одна последняя “stsim=7”?
Ведь цикл while должен отработать польностью, до истощения Serial-a.
Спасибо.

void setup()
{
Serial.begin(9600);
}

void loop()
{
  static byte stsim=0;
  
    if (Serial.available() > 0)
    {
        while (Serial.available() >0)
        {
            stsim++;
            char sim = Serial.read();
        }
        Serial.println("stsim="+String(stsim));
    }
}

Потому что байты прилетают не все сразу, а по очереди, циклу while больше одного за раз не достается

2 лайка

сделай небольшую задержку после считывания байта, и будет тебе счастье ))

        while (Serial.available() >0)
        {
            stsim++;
            char sim = Serial.read();
            delay(5);
        }

Значит, Serial.available() всегда равен 1?

Нет. Но если ты вычитываешь данные из буфера, как только они там появляются, то как там сможет быть больше одного? :wink:

Патамушта хардовый буфер всего один байт, на IBM был 16
у меня есть ESP32C3 с CH343, хардовый там явно не байт, но скетч видимо из своего буфера вычитывает…
Вот так работает:

void setup()
{
Serial.begin(115200);
delay(2000);
}

void loop()
{
  static byte stsim=0;
  
    if (Serial.available() > 0)
    {
        do 
        {
            stsim++;
            char sim = Serial.read();
            delayMicroseconds(1);
        }  while (Serial.available() > 0);

        Serial.println("stsim="+String(stsim));
    }
}
1 лайк

С Serial у меня работает проверенный метод:

void setup()
{
Serial.begin(9600);
}

void loop()
{
static String stroka="";
    if (Serial.available() > 0)
    {
        char sim = Serial.read();
        if (sim=='\n')
        {
            // Здесь обрабываю stroka, например, вывожу её в монитор
            Serial.println(stroka);
            stroka="";
        }
        else
        {
            if ((byte)sim!=13) stroka+=sim;
        }
    }
}

Но мне надо передавать нулевым байтом контрольную сумму, а затем значущую часть строки.
Но байт контрольной суммы может быть и '\r' и '\n'. Как отлавливать байт контрольной суммы - пока не знаю.

Никакого отношения к вопросу это не имеет. v258 дал совершенно верное описание. Вот только “небольшая задержка” - не очень красивое решение.
А для того, чтобы сделать решение красивым, нужна дополнительная информация.
Во-первых, известна ли заранее длина принимаемой строки?
Если “да”, все просто: if(Serial.available() == stringLength) ....
Если “нет”, можно периодически проверять длину строки, и как только период ожидания очередного приращения длины превысил время приема символа, значить, строка закончилась.

буфер циклический? если адрес головы и хвоста совпал то буфер пуст, если функции вычисления разницы (объёма не пустого циклического буфера) требует какой-то задержки то это полная хрень а не функция
PS не умение писать драйверы для серийного порта имеет длительную историю, вспомним хотя бы LINUX vs WINNT, последний прекрасно работ с компортами, а вот в линухе драйверы были полный отстой

Потому что сериал еще передаёт «признак новой строки» как дополнительный символ.
Ну или «перенос на новую строку», да как хотите его назовите - он всегда в ардуино иде по умолчанию включен.

Собственно, так я и предложил - считали байт, подождали, если есть еще что, повторили, нету ничего - вышли из цикла. Проверять буфер на длину строки имеет смысл только если длина строки заранее известна

на ESP32C3 всего одна микросекунда было достаточно… я врубился, что не так, это же булева функция, там или ноль или 1, а не количество оставшихся байт

а) зависит от скорости сериала
б) я поставил задержку от балды

Почему вы знак «переноса каретки» не учитываете то?
Оно там всё по 1 байту, что английские символы, что спец символы.

это работает быстрее микросекунды:

void setup()
{
Serial.begin(115200);
delay(2000);
}

void loop()
{
  static byte stsim=0;
  
    if (Serial.available() > 0)
    {
        int sb;
        do 
        {
            stsim++;
            char sim = Serial.read();
            //delayMicroseconds(1);
           sb = Serial.available();
        }  while (sb > 0);

        Serial.println("stsim="+String(stsim));
    }
}

Чой-та? ТС передает строку “abcdef”, на выходе имеет stsim=7
Все там считается ))

1 лайк

да мы и не о том вообще говорили )))

Аааа, я не внимательно вопрос прочёл..

Вот!
Нужно создать тему “Древняя история вычислительной техники” и все мемуары помещать туда.

Кстати - да.
Еще один часто используемый способ - пометить конец строки каким-нибудь символом, который заведомо нигде не используется, и выводить строку а печать только после получения этого символа (сам символ, естественно, на печать выводить не нужно).

3 лайка

Надо не забыть его там модератором сделать, а то не сдюжит. :smiley:

Удивительная способность у него, увести любую тему в

  • а, я…
  • а у меня…
1 лайк