IDE如何组织事物
首先,这是IDE如何组织您的“草图”:
- 主
.ino
文件与其所在文件夹的名称相同。因此,对于foobar.ino
in foobar
文件夹-主文件为foobar.ino。
.ino
该文件夹中的所有其他文件在主文件的末尾按字母顺序串联在一起(无论主文件在何处按字母顺序)。
- 此级联文件成为
.cpp
文件(例如foobar.cpp
)-放置在临时编译文件夹中。
- 预处理器“有帮助地”为其在该文件中找到的函数生成函数原型。
- 扫描主文件中的
#include <libraryname>
指令。这会触发IDE还将所有(提到的)库中的所有相关文件复制到临时文件夹中,并生成编译它们的指令。
- 任何
.c
,.cpp
或.asm
在草图夹中的文件被添加到构建过程作为单独的编译单元(即,它们以常规方式作为单独的文件编译)
- 所有
.h
文件也都被复制到临时编译文件夹中,因此您的.c或.cpp文件可以引用它们。
- 编译器将标准文件添加到构建过程中(如
main.cpp
)
- 然后,构建过程将上述所有文件编译为目标文件。
- 如果编译阶段成功,它们将与AVR标准库链接在一起(例如,提供给您
strcpy
等)。
所有这些的副作用是,可以将主草图(.ino文件)视为所有目的和用途的C ++。但是,如果不小心,函数原型的生成会导致模糊的错误消息。
避免预处理程序怪癖
避免这些特性的最简单方法是将主草图保留为空白(而不使用任何其他.ino
文件)。然后制作另一个标签(.cpp
文件),然后将您的内容放入其中:
#include <Arduino.h>
// put your sketch here ...
void setup ()
{
} // end of setup
void loop ()
{
} // end of loop
请注意,您需要添加Arduino.h
。IDE将为主草图自动执行此操作,但对于其他编译单元,则必须执行此操作。否则,它将不了解诸如String,硬件寄存器等之类的信息。
避免设置/主范式
您不必运行设置/循环概念。例如,您的.cpp文件可以是:
#include <Arduino.h>
int main ()
{
init (); // initialize timers
Serial.begin (115200);
Serial.println ("Hello, world");
Serial.flush (); // let serial printing finish
} // end of main
强制库包含
如果您使用“空草图”概念运行,则仍需要包括项目其他地方使用的库,例如在主.ino
文件中:
#include <Wire.h>
#include <SPI.h>
#include <EEPROM.h>
这是因为IDE仅扫描主文件以查找库使用情况。实际上,您可以将主文件视为“项目”文件,该文件指定使用了哪些外部库。
命名问题
在相同的单个.ino文件中声明C ++风格的类(听说过,但从未见过工作-可能吗?);
是的,这样编译就可以了:
class foo {
public:
};
foo bar;
void setup () { }
void loop () { }
但是,最好遵循常规做法:将声明放入.h
文件中,并将定义(实现)放入.cpp
(或.c
)文件中。
为什么“可能”?
如我的示例所示,您可以将所有内容放到一个文件中。对于较大的项目,最好有条理。最终,您进入了一个大中型项目的阶段,在这里您想将事物分成“黑匣子”-也就是说,一类要做一件事,做得很好,经过测试并且是独立的(越远越好)。
如果该类随后在项目中的多个其他文件中使用,则这是单独文件.h
和.cpp
文件起作用的地方。
该.h
文件声明了该类-也就是说,它为其他文件提供了足够的详细信息,以使其了解其功能,具有的功能以及如何调用它们。
该.cpp
文件定义(实现)了类-也就是说,它实际上提供了使类执行其操作的功能和静态类成员。由于您只想实现一次,因此在单独的文件中。
该.h
文件是包含在其他文件中的文件。该.cpp
文件由IDE编译一次,以实现类的功能。
图书馆
如果遵循此范例,则可以轻松地将整个类(.h
和.cpp
文件)移至库中。然后可以在多个项目之间共享。所需要做的只是制作一个文件夹(例如myLibrary
),然后将.h
和.cpp
文件放入其中(例如myLibrary.h
和myLibrary.cpp
),然后将该文件夹放入libraries
保存草图的文件夹中的文件夹内(Sketchbook文件夹)。
重新启动IDE,它现在知道该库。这确实非常简单,现在您可以在多个项目中共享该库。我经常这样做。
这里有更多细节。