Как последовательные мониторы интерпретируют данные ASCII base 10, полученные из сообщений Serial.print? - PullRequest
0 голосов
/ 07 августа 2020

Предыстория: я пытался создать систему, которая могла бы читать последовательные данные из входящего сообщения Serial.print, Serial.println или Serial.write. Затем, после анализа входящего сообщения, сохраните текст как переменную, которая затем будет распечатана на ЖК-дисплее или другом последовательном порту. Мне удалось заставить сообщения Serial.write работать успешно, но я столкнулся с проблемами при попытке проанализировать сообщения Serial.print. Поскольку сообщения Serial.print преобразуют двоичные символы ASCII в ASCII Base 10 перед его отправкой, и поскольку при последовательной связи при обмене данными отправляется по одному символу, я не смог разделить сообщение на отдельные символы ASCII после его получения. Например, когда был отправлен текст «красный», было получено «11410110010». Аналогичным образом «тест» вернул «11610111511610». (обратите внимание, что цифра «10», добавленная в конце обоих из них, - это символы новой строки ['\ n'])

В поисках решения этой проблемы я попытался посмотреть, как IDE Arduino делает это через просмотр исходного кода Serial Monitor на GitHub. Это то, что я обнаружил с моим ограниченным пониманием Java:

  • Я сначала начал с https://github.com/arduino/Arduino/blob/master/app/src/processing/app/SerialMonitor.java, который создает Serial Monitor GUI. Он расширил "Abstract Monitor", поэтому я пошел посмотреть, что он делает.
  • В https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractTextMonitor.java он обрабатывает слушателей и другие надстройки, которые выполняет Serial Monitor (например, отметки времени, автопрокрутка и окончания строк). Он расширил "Abstract Monitor", так что я пошел посмотреть, что он делает.
  • В https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractMonitor.java, я почти заблудился. Из того, что я вижу, похоже, что он выполняет критически важные функции последовательной связи (такие как открытие и закрытие связи, установка скорости передачи и т. Д. c), но я, вероятно, пропустил / не мог понять разделы, которые касаются функциональность, которую я искал.

Вот код и оборудование, которое я использовал, если это было полезно. Кроме того, если потребуется какая-либо другая информация, сообщите мне.

Устройство-отправитель: Sparkfun Pro Micro

Устройство-получатель: Arduino Duemilonove

Контакт 14 Pro Micro подключен к контакту 9 Duemilonove

Контакт 16 Pro Micro подключен к контакту 8 Duemilonove

ЖК-дисплей правильно настроен на Duemilonove с помощью контактов, указанных в коде приемника

Код отправителя (Pro Micro):

//If anything is sent from the Arduino IDE's Serial Monitor to the Device,
//foreword that message to the device connected to its Software Serial pins (The Receiver/ The Duemilonove)

#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 16);

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200);
}

void loop() {
  if (Serial.available()) {      // If anything comes in Serial (USB),
    mySerial.print(Serial.read());   // read it and send it out mySerial (Software Serial)
  }
}

Код получателя (Duemilonove):

#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
//SoftwareSerial mySerial(14, 16); for pro micro
SoftwareSerial mySerial(8, 9); //for Uno or Duemilanove
char lineOne[16];
char lineTwo[16];
char tempChar;
bool change = false;
bool newLineBuffer = false;

void setup() {
  Serial.begin(115200);
  mySerial.begin(115200);
  lcd.begin(16, 2);
}

void loop() {
  SerialCheck();
  newLineShift();
  updateLCD();
}
void SerialCheck() {
  if (mySerial.available()) {      // If anything comes in mySerial (Software Serial Port),
    tempChar=mySerial.read();
    change=true;
  }

  if (Serial.available()) {     // If anything comes in Serial (USB port)
    tempChar=Serial.read();
    change=true;
  }
}
void newLineShift(){
  if(change){
    if(tempChar=='\n'){
      if(newLineBuffer){
        lineChange();
      }else{
        newLineBuffer=true;
      }
    }else{
      if(newLineBuffer){
        lineChange();
      }
      for (byte i = 0; i < 15; i = i + 1) {
        if(!lineOne[i]=='\0'){
          //Do nothing lol
        }else{
          lineOne[i]=tempChar;
          break;
        }
      }
      newLineBuffer=false;
    }
  }
  
}
void updateLCD(){
  if(change){
    lcd.clear();
    Serial.println("Line Two is: "+ (String)lineTwo);
    lcd.setCursor(0, 0);
    lcd.print(lineTwo);
    Serial.println("Line One is: "+ (String)lineOne);
    lcd.setCursor(0, 1);
    lcd.print(lineOne);
  }
  change=false;
  tempChar='\0';
}
void lineChange(){
  for (byte i = 0; i < 15; i = i + 1) {
      lineTwo[i]=lineOne[i];
      lineOne[i]='\0';
    }
}

1 Ответ

0 голосов
/ 07 августа 2020

read () возвращает int. Они делают это, чтобы он мог вернуть -1, когда там нечего читать. Обычно нас интересует только прочитанный байт, который находится в младших 8 битах.

Итак, когда вы пишете это:

mySerial.print(Serial.read());

вызываемая версия печати один для печати переменной типа int. Эта версия разбивает число на ascii, и '114' из r красного становится '1', '1' и '4'.

Вместо этого вы хотите вызвать версию для печати символ. Вы беспокоитесь только о переменной char, которая все равно была прочитана. Так что попробуйте следующее:

char c = Serial.read();
mySerial.print(c);

или даже:

mySerial.print((char)Serial.read());

, и вы получите желаемую версию печати. ​​

В качестве альтернативы вы можете просто написать байт, который вы читаете напрямую, используя запись вместо печати. Поскольку запись отправляет байт в точности как есть, она отправит 114 байт точно так же, как и при его чтении, и на другом конце вы увидите букву r.

mySerial.write(Serial.read());
...