为什么全局对象构造函数在 Arduino 中只打印前 2 个字符?

Why does global object constructor print only the first 2 chars in Arduino?

我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:

Fred.h

#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
  {
   public:
     Fred();
  };
#endif

Fred.cpp

#include "Fred.h"
Fred::Fred()
{
  Serial.begin(115200);
  Serial.println("Hello Arduino!");
}

在草图中,我刚刚全局初始化了 class 对象:

#include <Fred.h>
Fred a;
void setup()
{}
void loop()
{}

它应该打印 Hello Arduino!在串行终端中,但它只打印前两个字节 "He",这很奇怪!我读过有关 SIOF(静态初始化顺序 Fiasco)的文章,这可能是问题所在,但如果是这样,为什么它打印 2 个字节而不是未在 all.If 处打印 我在设置函数中声明了它正常工作的对象。

首先,由于 SIOF,尝试在另一个单例的构造函数中调用单例的方法是错误的。在对象可能尚未构造时调用该对象的方法是不好的,并且可能导致奇怪的行为。所以,如果通过在 Serial 和 Fred 上避免 SIOF 问题消失了,你不需要质疑为什么它打印 2 个字节。

编辑: 如何避免 SIOF?有很多方法可以做到这一点。但是如果你想为 Fred 保留一个单例,你应该使用 COFU (https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Construct_On_First_Use)

为了避免 SIOF,你可以这样做:

我创建了一个名为 Fred 的 class,这里是 .h 和 .cpp 文件:

Fred.h

#ifndef Fred_h
#define Fred_h
#include "Arduino.h"
class Fred
  {
   public:
     Fred();
     void printMessage();
  };
#endif

Fred.cpp

#include "Fred.h"
Fred::Fred()
{
    // nothing to do here
}

void Fred::printMessage()
{
  Serial.println("Hello Arduino!");
}

草图中:

#include <Fred.h>
Fred a;
void setup()
{
    Serial.begin(9600);
}
void loop()
{
    a.printMessage();
}

希望这对您有所帮助。

您无法从静态对象的构造函数访问 Serial,因为无法保证 Serial 会被设置。在输入 main.

之前,您不想执行任何 "real work"

arduino的串口实现大概只有两个字符的硬件缓冲。一旦发送了前两个,剩下的就被扔掉了,因为对它们进行排队和安排中断服务的必要逻辑可能还没有设置。

所以第一个字符立即开始发送。第二个字符位于等待第一个字符完成的硬件缓冲区中。剩余的字符应该被传送到中断处理程序(这样每次缓冲区为空,因为前一个字符已经完全发送,一个新的字符可以开始被发送出去),但显然还没有设置。