Почему этот простой код последовательного монитора не работает?

Следующий код повторяет все, что Arduino получает через контакт приемника. Идея состоит в том, что Arduino будет отображать все данные в буфере в одной и той же строке, начиная с новой строки, одновременно отображая следующие данные, полученные в буфере.

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

void loop()
{
  if(Serial.available())
    {
        int count = Serial.available();
        for(int i = 0; i < count; i++)
        {
            char character = Serial.read();
            Serial.print(character);
        }
        Serial.print("\n");
    }
}

Когда я запускаю код, он печатает символы построчно. например, если я введу слово «БЫСТРО»; это повторяет следующее

Q
U
I
C
K

Хотя я думаю, что это должно звучать эхом

QUICK

Пожалуйста, помогите мне.

, 👍1


1 ответ


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

4

Похоже, вы предполагаете, что строка "QUICK" отправляется как один пакет символов, поскольку вы отправляете его одним нажатием клавиши из последовательного монитора. Но последовательный порт (UART) — это «последовательный» интерфейс. протокол, что означает, что каждый байт (также известный как символ кодировки ASCII) отправляется последовательно.

При скорости 9600 бод для передачи каждого байта потребуется около 1 мс. Кроме того: небольшие случайные задержки могут быть введены ПК или при соединении USB (если вы осуществляете связь через чип USB-Serial, например, когда вы подключаете Uno через USB).

Ваш код выполняется быстрее, чем данные поступают на микроконтроллер Unos. Первое предложение if вводится, как только в вашем последовательном буфере появляется один байт. Затем вы начинаете читать данные из буфера, но в этот момент больше байтов не поступает. Таким образом, цикл завершается после одной итерации.

Если вы хотите обрабатывать последовательные данные построчно, вам следует отправить окончание строки из последовательного монитора (или любой другой программы, которую вы используете) с помощью опции окончания строки. Распространенным способом является использование \n, также известного как символ новой строки, в качестве конца строки. Затем в вашем коде вы должны читать данные до тех пор, пока не получите символ новой строки.

Это можно сделать несколькими способами. Один из способов — считывать каждый поступающий символ в ваш собственный буфер, который достаточно велик, чтобы вместить максимальное количество символов, которое может встретиться в ваших сообщениях. Затем при получении символа новой строки вы можете обработать данные в буфере. Переменные содержат текущую позицию в буфере:

unsigned int pos = 0;
char buffer[20] = ""; // достаточно места для 19 символов + нулевой символ для правильного завершения строки

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

void loop(){
  if(Serial.available()){
    char c = Serial.read();
    if(c != '\n'){
      buffer[pos] = c; // Добавляем полученный символ в буфер
      if(pos < sizeof(buffer) - 1){
        // увеличиваем переменную позиции, чтобы она указывала на следующую позицию в буфере
        // но только если в буфере осталось достаточно места
        // иначе этот код перезапишет последний символ
        pos++;
      }
    } else {
      buffer[pos] = 0; // Правильное завершение строки
      // Обработка сообщения здесь
      Serial.println(buffer);
      // Сбрасываем буфер, устанавливая позицию обратно в ноль
      pos = 0;
    }
  }
}

Примечание. Для этого кода ваша функция loop() должна выполняться достаточно быстро, чтобы вы не пропустили больше данных, чем может вместить внутренний буфер Serial (я думаю, 32 символа). Поэтому вы, вероятно, не захотите использовать длинные задержки (что в любом случае почти всегда является плохой идеей, см. неблокирующее кодирование и функцию millis()).

,