为什么多个相同的函数调用在Arduino上的执行时间有显着差异?

问题描述 投票:0回答:1

我在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.
performance logging arduino serial-port runtime
1个回答
0
投票

串口输出会被缓冲,实际发送需要一些时间,具体取决于波特率。 如果缓冲区中有空间,则 Serial.print 只是将新字符添加到缓冲区并返回。 如果缓冲区中没有空间,则 Serial.print 必须阻塞,直到有空间为止。

© www.soinside.com 2019 - 2024. All rights reserved.