Использование библиотек Arduino для обычного кода AVR

У меня есть Arduino Uno и среда Linux. Хотя Arduino IDE великолепен и все такое, однако он не дает мне много информации, если что-то пойдет не так. И это также становится мучительно медленным и иногда перестает общаться с чипом.

Альтернативой является кодирование моего Arduino Uno с использованием AVR-GCC/g++ и AVRDude toolchain. Однако мне бы очень хотелось иметь доступ к тем же функциям, что и в Arduino (например, Serial, digitalWrite и т. Д.) При программировании с использованием простого текстового редактора и инструментов командной строки.

Поэтому я попытался найти заголовочный файл со всеми определенными функциями, например, "Arduino.h" в /usr/share/arduino/hardware/arduino/cores/arduino,

Я использовал это для компиляции (используя для этого make-файл)

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"). Итак, какой именно заголовочный файл нужно включить, чтобы убедиться, что я могу использовать те же функции? Или я что-то пропустил?

3 ответа

Решение

Как получить определения для 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

Судар дал хороший совет, выступая за использование Makefile для AVR, который настроен на включение определений функций Arduino. (Я свяжусь с моим и объясню это ниже.)

В моем make-файле я обработал эту операцию следующим образом:

# 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()и я хочу сам определить это в моих собственных файлах проекта.

Необходимые заголовочные файлы

Конечно, вы также должны передать avr-gcc флаг включения для заголовков arduino:

-I$(ARDCOREDIR)

И вы должны включить файл Ardhuino.h в ваш фактический код проекта:

#include <Arduino.h>

Заголовочный файл Arduino.h будет включать в себя все остальные заголовочные файлы Arduino, включая файл распиновки, который содержит определения для выводов Arduino. Разные Arduinos должны иметь разные файлы распиновки, поэтому определите, какой тип вы используете, и скажите avr-gcc включить каталог, содержащий соответствующий файл распиновки. Если вы используете стандартный Arduino (UNO), используйте следующее:

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

Мой Makefile

Ваш процесс сборки должен не только реализовать несколько инструкций, описанных выше, но и знать, как создать файл.hex, который должен быть запрограммирован на вашем Arduino (или AVR). Поэтому, это хорошая идея использовать make-файл.

Я не люблю перестраивать свой make-файл для каждого проекта, поэтому у меня есть только один базовый make-файл на моей машине, и у каждого проекта есть свой собственный очень короткий make-файл, который вызывает include включить базовый make-файл. Вы можете найти мой базовый 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

NB: если вы собираетесь использовать мой базовый make-файл, убедитесь, что вы установили переменную ARDDIR (который появляется в верхней части файла), чтобы указать на каталог Arduino на вашем компьютере.

Я использую make-файл для Arduino, который позволяет мне использовать как пользовательские, так и системные библиотеки. Вам не нужно использовать Arduino IDE, но в то же время вы можете использовать библиотеки, предоставляемые им.

Возможно, вы захотите установить подробные параметры компиляции в Arduino IDE. Затем скомпилируйте что-нибудь и посмотрите вывод IDE. Он скажет вам, где находится файл.cpp и какие параметры компилятора он использует. Как только вы заглянете в файл.cpp, вы сразу увидите, что вам нужно включить.

После этого make-файлы становятся намного проще для понимания. Если у вас нет опыта работы с make, я бы посоветовал вам избегать его и вместо этого использовать scons. Scons написан на Python. Таким образом, вы сразу получаете выгоду от гораздо более простой отладки.

Другие вопросы по тегам