20

我有一个 Arduino Uno 和一个 Linux 环境。虽然 Arduino IDE 非常棒,但是如果出现问题,它并没有给我太多的输入。而且它也会变得非常缓慢,有时会停止与芯片的通信。

另一种方法是使用 AVR-GCC/g++ 和 AVRDude 工具链对我的 Arduino Uno 进行编码。但是,我非常希望在使用简单的文本编辑器和命令行工具进行编程时访问与 Arduino 中相同的功能(如SerialdigitalWrite等)。

所以我试图找到所有定义的函数的头文件,即“Arduino.h” /usr/share/arduino/hardware/arduino/cores/arduino

我用它来编译(使用makefile来做这个)

avr-gcc -mmcu=atmega328p -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=testarduino.o -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standard -std=gnu99 -MMD -MP -MF .dep/testarduino.elf.d testarduino.o --output testarduino.elf -Wl,-Map=testarduino.map,--cref     -lm

编译这段代码:

#include "Arduino.h"

int main(void)
{
    init();
    pinMode(13,OUTPUT);
    while(1){
    digitalWrite(13,HIGH);
    delay(1000);
    digitalWrite(13,LOW);
    delay(1000);
    }
    return 0;
}

但是,当我尝试编译时,似乎没有一个函数被识别(说未定义的对'xxxxxxxxx'的引用)。那么,为了确保我可以使用相同的功能,需要包含的确切头文件是什么?或者还有什么我错过的吗?

4

3 回答 3

21

如何获取定义undefined reference

该消息undefined reference to 'xxxxxxxxx'意味着链接器找不到相关函数的实际定义(不仅仅是声明)。

当链接器找不到函数的定义时,通常可以在 lib 文件(例如 *.so 或 *.dll)或源文件(例如 *.cpp 或 *.c)中找到该定义。对于您的 Arduino,您需要告诉 avr-gcc 编译和链接 Arduino *.cpp 文件。您需要来自 Arduino 核心的所有源文件。

ARDCOREDIR = <my arduino folder>/hardware/arduino/cores/arduino

Sudar 给出了很好的建议,提倡使用用于 AVR 的 Makefile,该 Makefile 配置为包含 Arduino 函数定义。(我将链接到我的并在下面解释。)

在我的 makefile 中,我按如下方式处理了此操作:

# CPP_SOURCE_FILES is a previously-defined variable, holding my project's source files
CPP_SOURCE_FILES += $(filter-out $(ARDCOREDIR)/main.cpp, $(wildcard $(ARDCOREDIR)/*.cpp))

请注意,我省略了 main.cpp 文件,因为 Arduino main.cpp 文件定义了main(),我希望自己在自己的项目文件中定义它。

必要的头文件

当然,您还必须为 arduino 标头传递 avr-gcc 一个包含标志:

-I$(ARDCOREDIR)

您必须在实际项目代码中包含 Ardhuino.h 文件:

#include <Arduino.h>

Arduino.h 头文件将包含所有其他 Arduino 头文件,包括 pinout 文件,其中包含 Arduino 引脚的定义。不同的 Arduino 必须有不同的 pinout 文件,因此请确定您使用的是哪种类型,并告诉 avr-gcc 包含包含适当 pinout 文件的目录。如果您使用的是标准 Arduino (UNO),请使用以下命令:

-I$(ARDCOREDIR)/../../variants/standard

我的 Makefile

您的构建过程不仅需要执行上述几条指令,还需要知道如何制作 .hex 文件,该文件将被编程到您的 Arduino(或 AVR)上。因此,使用 makefile 是一个好主意。

我不喜欢为每个项目重建我的makefile,所以我的机器上只有一个基本makefile,每个项目都有自己的,非常短的makefile,它调用include包含基本makefile。你可以在这里找到我的基本 makefile

我机器上单个项目的简短(非基础)Makefile 示例:

# This is the name of the file that shall be created. (It is also the name of my primary source file, without the file extension.)
TARGET = temp

# create a variable that only pertains to this project
MY_OWN_LIBRARY_DIR = /usr/home/MJ/Arduino/libraries/mj_midi

# "EXTRAINCDIRS" is a variable used by the base makefile. The base makefile creates a -I compiler flag for every item in the "EXTRAINCDIRS" list.
EXTRAINCDIRS = $(MY_OWN_LIBRARY_DIR)

# specify *.c source files pertaining to my project
SRC =

# specify *.cpp source files pertaining to my project
PSRC = temp.cpp $(MY_OWN_LIBRARY_DIR)/midi-listener.cpp $(MY_OWN_LIBRARY_DIR)/midi-song.cpp

# specify additional (non-core) Arduino libraries to include
ARDLIBS = SoftwareSerial

# include my base makefile
include /d/dev/avr/Makefile.base

注意:如果您要使用我的基本 makefile,请确保将变量ARDDIR(显示在文件顶部附近)设置为指向您机器上的 Arduino 目录。

于 2013-05-03T18:26:07.817 回答
5

我为 Arduino使用makefile ,它允许我同时使用用户和系统库。您不必使用 Arduino IDE,但同时可以使用它提供的库。

于 2012-11-08T10:47:07.320 回答
1

您可能希望将 Arduino IDE 编译选项设置为详细。然后编译一些东西并观察 IDE 的输出。它会告诉您 .cpp 文件的位置以及它使用的编译器选项。查看 .cpp 文件后,您会立即看到需要包含的内容。

之后,makefile 变得更容易理解。如果您之前没有经验,我的建议是避免它并改为使用 scons。Scons 是用 Python 编写的。因此,您可以立即从更简单的调试中受益。

于 2013-10-28T17:33:47.270 回答