如何解决是什么导致我的程序延迟?读取串行数据并解析 ESP32:Arduino IDE
在我的测试程序中,出现意外延迟(大约 100 毫秒)。 我正在尝试从 GPS 读取数据(作为 NMEA 语句)并解析它。 目前,程序读取数据,如果是 NMEA 语句,它会尝试解析它。问题是,我在某些消息之间延迟了大约 100 毫秒。
GPS 的波特率为 9600,这会导致问题吗?
我的方法是解析 GGA 语句,并尽快将修改后的自定义语句重新发送到不同的串行端口 (USB),其中添加了传感器数据(应该看起来像最初来自 GPS - 如此同步)
我的输出如下所示: Output from program
13:38:31.306 -> $GPGSV,3,1,10,02,25,125,06,28,083,12,79,312,15,05,189,0*6E
13:38:31.306 -> $GPGSV,0*6E
13:38:31.306 -> 5
13:38:31.306 -> $GPGSV,2,17,11,042,19,32,049,24,59,149,36,270,0*60
13:38:31.410 -> $GPGSV,0*60
13:38:31.410 -> 112
13:38:31.410 -> $GPGSV,29,04,210,303,0*62
13:38:31.410 -> $GPGSV,0*62
13:38:31.410 -> 3
13:38:31.410 -> $GLGSV,69,00,219,70,23,71,21,324,73,293,0*75
13:38:31.544 -> $GLGSV,0*75
13:38:31.544 -> 113
13:38:31.544 -> $GLGSV,78,101,57,075,80,51,314,81,56,0*72
13:38:31.544 -> $GLGSV,0*72
13:38:31.544 -> 7
接收到字节后直接打印第一句。收到完整的句子后,第二个句子会打印为字符串。
这是我的代码:
#define RXD2 13
#define TXD2 12
#define SERIAL_SIZE_RX 1024 // used in Serial.setRxBufferSize()
bool bNMEAstarted = false;
String NMEAsent;
unsigned long currentTime,lastTime;
void setup() {
Serial.begin(115200);
delay(15);
//GPS serial
Serial2.begin(9600,SERIAL_8N1,RXD2,TXD2);
delay(150);
//Serial2.setRxBufferSize(SERIAL_SIZE_RX); //increase buffer size to 1024 bytes
currentTime = millis();
lastTime = currentTime;
}
void loop() {
receiveFromGPS();
}
void receiveFromGPS(){
byte incomByte1 = 0;
if (Serial2.available()>0){
incomByte1 = Serial2.read();
Serial.write(incomByte1);
// Parsing NMEA sentence
if (incomByte1 == '$') { //means it is NMEA sentece
bNMEAstarted = true;
NMEAsent = ""; //empty the string
}
if (bNMEAstarted) {
NMEAsent += (char)incomByte1; //add every character to NMEA sentence
if (incomByte1 == 10) { //ASCII(10) <LF> (LineFeed) ends the message
bNMEAstarted = false;
//do parsing after the end on sentence
parseNMEA(NMEAsent);
}
}
}
}
void parseNMEA(String sNMEA) {
//if (sNMEA.substring(3,6) == "GGA") { // GGA Message found
//only print every NMEA sentence and time between each measurements
Serial.print(sNMEA);
currentTime = millis();
Serial.println(currentTime-lastTime);
//}
lastTime = currentTime;
}
解决方法
较长的 GGA 语句是 64 字节长。在 9600 波特时,一个字节的传输时间大约为 1 毫秒。如果您的 GPS 在它们之间没有任何延迟地吐出 GGA 句子,那么它应该每 64 毫秒接收一个句子 - 这是您的平均水平。
这里令人困惑的部分可能是这样的事实:有时读取似乎发生得非常快( 100 毫秒)。这是由 UART 的缓冲区引起的。 ESP32 中的 UART 在接收端有一个 128 B 的 FIFO 缓冲区,它接收传入的字节并且在 one of two conditions 发生之前不会将它们给你:
- 缓冲区已满(未记录确切数量)或
- 缓冲区未满(但保存了一些数据)并且发生了 RX 超时(未记录确切的超时值)。
这会造成您最终会获得数据的情况,但它有点……断断续续。很抱歉,我不知道如何解决这个问题,因为 UART 缓冲区不能轻易绕过(或者,至少,没有关于如何做到这一点的官方文档)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。