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

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

本文关键字:字符 Arduino 对象 全局 构造函数 打印 为什么      更新时间:2023-10-16

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

弗雷德·

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

弗雷德.cpp

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

在草图中,我只是全局初始化了类对象:

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

它应该在串行终端中打印Hello Arduino!,但它只打印前两个字节"He",这很奇怪!我已经阅读了有关 SIOF(静态初始化顺序惨败)的信息,这可能是问题所在,但如果是这样,为什么它会打印 2 个字节而不是根本不打印。如果我在设置函数中声明了对象,它可以正常工作。

不能从静态对象的构造函数访问Serial,因为无法保证将设置Serial。在输入main之前,您不想做任何"真正的工作"。

在arduino的串行端口实现中可能只有两个硬件缓冲字符。一旦发送了前两个,其余的就会被丢弃,因为排队和安排中断服务的必要逻辑可能尚未设置。

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

首先,由于 SIOF,尝试在另一个单例的构造函数中调用单例的方法是错误的。在对象可能尚未构造的情况下调用该对象的方法是不好的,并可能导致奇怪的行为。因此,如果通过避免串行和弗雷德上的SIOF问题消失了,则无需质疑为什么它会打印2个字节。

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

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

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

弗雷德·

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

弗雷德.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();
}

希望这有帮助。