我在Arduino上编写了我的类
Adf
、bool Adf::sendAndReceive(char *data, uint8_t length)
的成员函数,它通过Adf::pSerial
指向的串行端口发送一个字符数组,然后读取rx缓冲区。 rx 和 tx 线已连接,因此每个发送的字节都会回显到 rx 缓冲区中。此外,我使用 ArduinoLog 库来跟踪整个流量。现在我遇到了一个非常奇怪的情况:我使用相同的参数连续调用 sendAndReceive
两次,并且在第一次调用期间,记录传出消息花费了不到 1 毫秒,但在第二次调用中花费了 29 毫秒.
具有相同参数的同一个函数调用所花费的时间怎么可能不同?
这些是被调用的函数:
bool Adf::sendAndReceive(char *data, uint8_t length)
{
uint8_t rxTxLength = 0;
// send data
unsigned long start = millis();
rxTxLength = pSerial->write(data, length);
unsigned long end = millis();
Logger.trace("TX start: %lu, end: %lu, duration: %lu\n", start, end, end - start);
// STRANGE BEHAVIOUR HAPPENS HERE ===================
unsigned long start2 = millis();
// Trace the sent bytes
Logger.trace("%s - data: ", __func__);
traceCharArray(data, rxTxLength);
unsigned long end2 = millis();
Logger.trace("Trace start: %lu, end: %lu, duration: %lu\n", start2, end2, end2 - start2);
// ==================================================
// handle write error
unsigned long start3 = millis();
if (rxTxLength != length)
{
Logger.errorln("%s - Error writing to serial. Only %d of %d bytes written.",
__func__,
rxTxLength,
length);
return false; // Failure: error writing to serial
}
unsigned long end3 = millis();
Logger.trace("Error start: %lu, end: %lu, duration: %lu\n", start3, end3, end3 - start3);
// Read all echoed bytes
unsigned long start4 = millis();
char echo[length];
getAdfResponse(echo, length);
unsigned long end4 = millis();
Logger.trace("Echo start: %lu, end: %lu, duration: %lu\n", start4, end4, end4 - start4);
// Compare sent and echoed bytes
unsigned long start5 = millis();
if (memcmp(data, echo, length) != 0)
{
Logger.errorln("%s - Serial was not echoed correctly", __func__);
return false; // Failure: echoed bytes do not match sent bytes
}
unsigned long end5 = millis();
Logger.trace("Compare start: %lu, end: %lu, duration: %lu\n", start5, end5, end5 - start5);
return true; // Success: all bytes echoed correctly
}
void Adf::traceCharArray(char *data, uint8_t length)
{
for (int i = 0; i < length; i++)
{
Logger.trace("%x, ", static_cast<unsigned char>(data[i]));
/* static cast to ensure that the data is correctly interpreted as an
** unsigned value when logging in hexadecimal format */
}
Logger.traceln("");
}
问题出现在“Trace”部分,其中调用了函数
Adf::traceCharArray
。
这是主文件
#include <Arduino.h>
#include <ADF.h>
#define ADDRESS_WIRE 33
#define BAUD_RATE 2400
Adf adf(ADDRESS_WIRE, &Wire1, BAUD_RATE, &Serial3);
char msg = 0x81;
void setup()
{
// initialize Serial
Serial.begin(9600);
Serial.println("Hello ADF");
adf.Logger.begin(LOG_LEVEL_TRACE, &Serial, false);
// initialize ADF
if (!adf.begin())
{
Serial.println("Init failed.");
}
if (!adf.sendAndReceive(&msg, 1))
{
Serial.println("sendAndReceive failed.");
}
Serial.println("====================================");
if (!adf.sendAndReceive(&msg, 1))
{
Serial.println("sendAndReceive failed.");
}
// signal setup OK
Serial.println("Setup done.");
}
void loop()
{
}
这是记录器打印的输出(以及我的笔记):
---- Opened the serial port COM3 ----
13:29:10:875 -> Hello ADF
13:29:16:384 -> TX start: 5513u, end: 5513u, duration: 0u
13:29:16:429 -> sendAndReceive - data: 81,
13:29:16:458 -> Trace start: 5513u, end: 5513u, duration: 0u <--- compare this
13:29:16:503 -> Error start: 5513u, end: 5513u, duration: 0u
13:29:16:552 -> getAdfResponse - resp: 81,
13:29:16:581 -> Echo start: 5545u, end: 5574u, duration: 29u
13:29:16:626 -> Compare start: 5621u, end: 5621u, duration: 0u
13:29:16:677 -> ====================================
13:29:16:716 -> TX start: 5709u, end: 5709u, duration: 0u
13:29:16:761 -> sendAndReceive - data: 81,
13:29:16:790 -> Trace start: 5753u, end: 5782u, duration: 29u <--- to this
13:29:16:835 -> Error start: 5830u, end: 5830u, duration: 0u
13:29:16:884 -> getAdfResponse - resp: 81,
13:29:16:913 -> Echo start: 5877u, end: 5906u, duration: 29u
13:29:16:958 -> Compare start: 5953u, end: 5953u, duration: 0u
13:29:17:007 -> Setup done.
问题: 即使传递相同的参数,为什么第一次调用
Adf::traceCharArray
需要 0 毫秒,第二次需要 29 毫秒?
注意:经过进一步的研究,我发现如果直接调用
Adf::traceCharArray
(而不是从另一个函数内),则不会出现此问题:
在主文件中
unsigned long start = millis();
adf.traceCharArray(&msg, 1);
unsigned long end = millis();
Serial.print("duration: ");
Serial.println(end - start);
Serial.println("====================================");
unsigned long start2 = millis();
adf.traceCharArray(&msg, 1);
unsigned long end2 = millis();
Serial.print("duration: ");
Serial.println(end2 - start2);
和输出
---- Opened the serial port COM3 ----
13:46:12:418 -> Hello ADF
13:46:17:927 -> 81,
13:46:17:935 -> duration: 0
13:46:17:958 -> ====================================
13:46:17:988 -> 81,
13:46:17:992 -> duration: 0
13:46:18:004 -> Setup done.
串口输出会被缓冲,实际发送需要一些时间,具体取决于波特率。 如果缓冲区中有空间,则 Serial.print 只是将新字符添加到缓冲区并返回。 如果缓冲区中没有空间,则 Serial.print 必须阻塞,直到有空间为止。