串行监视器如何解释从 Serial.print 消息生成的 ASCII base 10 数据?

How do Serial Monitors interpret the ASCII base 10 data produced from Serial.print messages?

背景: 我试图创建一个系统,该系统能够从传入的 Serial.print、Serial.println 或 Serial.write 消息中读取串行数据。然后,在解析传入消息后,将文本保存为变量,然后将其打印到 LCD 或不同的串行端口上。我能够让 Serial.write 消息成功运行,但我 运行 在尝试解析 Serial.print 消息时遇到问题。由于 Serial.print 消息在发送之前将二进制 ASCII 字符转换为 Base 10 ASCII,并且由于串行通信在通信时一次发送一个字符,因此我无法在收到消息后将其分成单独的 ASCII 字符。例如,发送文本“red”时,收到“11410110010”。同样,“测试”返回“11610111511610”。 (请注意,两者末尾的'10'为换行符['\n'])

为了寻找这个问题的解决方案,我试图通过查看 GitHub 上串行监视器的源代码来了解 Arduino IDE 是如何做到的。这是我在对 Java:

的有限理解下发现的

这是我使用的代码和硬件,如果有帮助的话。除此之外,如果需要任何其他信息,请告诉我。

发送设备:Sparkfun Pro Micro

接收设备:Arduino Duemilonove

Pro Micro 的引脚 14 连接到 Duemilonove 的引脚 9

Pro Micro 的引脚 16 连接到 Duemilonove 的引脚 8

LCD 已正确配置为 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]=='[=12=]'){
          //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='[=12=]';
}
void lineChange(){
  for (byte i = 0; i < 15; i = i + 1) {
      lineTwo[i]=lineOne[i];
      lineOne[i]='[=12=]';
    }
}

read() returns 一个整数。他们这样做是为了 return -1 当没有什么可读的时候。通常我们只对读取的低 8 位字节感兴趣。

所以当你这样写的时候:

mySerial.print(Serial.read());

调用的 print 版本是用于打印 int 变量的版本。该版本将数字分解为 ascii,红色 r 中的“114”变为“1”、“1”和“4”。

相反,您想调用打印字符的版本。您只担心无论如何都读取的 char 变量。所以试试这个:

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

甚至:

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

这将为您提供所需的打印版本。

或者,您可以使用 write 而不是 print 直接写入您读回的字节。由于 write 完全按原样发送字节,它会像读取它一样发送 114 字节,你会在另一端看到 'r'。

mySerial.write(Serial.read());