串行监视器如何解释从 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:
的有限理解下发现的
- 我首先从 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/SerialMonitor.java 开始创建串行监视器 GUI。它扩展了“抽象监视器”,所以我去看看它做了什么。
- 在 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractTextMonitor.java 中,它处理串行监视器执行的侦听器和其他附加组件(例如时间戳、自动滚动和行尾)。它扩展了“抽象监视器”,所以我去看看它做了什么。
- 在 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractMonitor.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());
背景: 我试图创建一个系统,该系统能够从传入的 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:
的有限理解下发现的- 我首先从 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/SerialMonitor.java 开始创建串行监视器 GUI。它扩展了“抽象监视器”,所以我去看看它做了什么。
- 在 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractTextMonitor.java 中,它处理串行监视器执行的侦听器和其他附加组件(例如时间戳、自动滚动和行尾)。它扩展了“抽象监视器”,所以我去看看它做了什么。
- 在 https://github.com/arduino/Arduino/blob/master/app/src/processing/app/AbstractMonitor.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());