Программируем Arduino на чистом Си

Повышение квалификации

В жизни ардуинщика рано или поздно наступает момент, когда в штатной среде разработки становится тесно. Если скетчам перестает хватать памяти, требуется жесткий реалтайм и работа с прерываниями или просто хочется быть ближе к железу — значит пришло время переходить на C. Бывалые электронщики при упоминании Arduino презрительно поморщатся и отправят новичка в радиомагазин за паяльником. Возможно, это не самый плохой совет, но мы пока не будем ему следовать. Если отбросить Arduino IDE и язык wiring/processing, у нас в руках останется прекрасная отладочная плата, уже оснащенная всем необходимым для работы микроконтроллера. И, что немаловажно, в память контроллера уже зашит бутлоадер, позволяющий загружать прошивку без использования программатора.

Для программирования на языке C нам понадобится AVR GCC Toolchain.

Windows:
Устанавливаем WinAVR, который содержит все необходимое.

Debian и Ubuntu:
sudo apt-get install gcc-avr binutils-avr avr-libc


MacOs X:
Устанавливаем CrossPack for AVR Development

Также нам потребуется установленная Arduino IDE, т.к. она содержит утилиту avrdude, которая нужна для загрузки прошивки в контроллер. CrossPack тоже содержит avrdude, но версия, идущая с ним, не умеет работать с Arduino.

После того, как все установлено, создадим наш первый проект. Для начала напишем Makefile. Он позволит нам избежать ввода длинных команд вручную при каждой компиляции и загрузке прошивки.

 

#Контроллер, установленный на плате. Может быть другим, например atmega328 
DEVICE     = atmega168

#Тактовая частота 16 МГц 
CLOCK      = 16000000

#Команда запуска avrdude. Ее нужно скопировать из Arduino IDE.
AVRDUDE = /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude -C/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf -carduino -P/dev/tty.usbserial-A600dAAQ -b19200 -D -p atmega168

OBJECTS    = main.o

COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)

all:	main.hex

.c.o:
	$(COMPILE) -c $< -o $@

.S.o:
	$(COMPILE) -x assembler-with-cpp -c $< -o $@

.c.s:
	$(COMPILE) -S $< -o $@

flash:	all
	$(AVRDUDE) -U flash:w:main.hex:i

clean:
	rm -f main.hex main.elf $(OBJECTS)

main.elf: $(OBJECTS)
	$(COMPILE) -o main.elf $(OBJECTS)

main.hex: main.elf
	rm -f main.hex
	avr-objcopy -j .text -j .data -O ihex main.elf main.hex
	avr-size --format=avr --mcu=$(DEVICE) main.elf






В этом файле нам нужно вписать свою команду для запуска avrdude. На разных системах она будет выглядеть по разному. Чтобы узнать свой вариант, запускаем Arduino IDE и в настройках ставим галочку «Show verbose output during upload».


Теперь загружаем в Arduino любой скетч и смотрим сообщения, выводимые в нижней части окна. Находим там вызов avrdude, копируем все, кроме параметра -Uflash и вставляем в Makefile после «AVRDUDE = ».


Небольшое замечание: все отступы в Makefile делаются символами табуляции (клавишей Tab). Если ваш текстовый редактор заменяет эти символы пробелами, команда make откажется собирать проект.

Теперь создадим файл main.c — собственно текст нашей программы, в которой традиционно помигаем светодиодом.

#include <avr/io.h>
#include <util/delay.h>

#define LED_PIN 5

int main() {
	DDRB |= 1 << LED_PIN;	
	while(1) {
		PORTB |= 1 << LED_PIN;
		_delay_ms(1000);
		PORTB &= ~(1 << LED_PIN);
		_delay_ms(1000);
	}
	return 0;
}



Наш проект готов. Откроем консоль в директории нашего проекта и введем команду «make»:


Как видим, размер получившейся прошивки составляет всего 180 байт. Аналогичный ардуиновский скетч занимает 1116 байт в памяти контроллера.

Теперь вернемся к консоли и введем «make flash» чтобы загрузить скомпилированный файл в контроллер:


Если загрузка прошла без ошибок, то светодиод, подключенный к 13 контакту платы, радостно замигает. Иногда avrdude не может найти плату или отваливается по таймауту — в этом случае может помочь передегивание USB кабеля. Также, во избежание конфликтов доступа к плате, не забудьте закрыть Arduino IDE перед командой «make flash».

Возможно многие вещи, описанные в этой статье, покажутся очевидными матерым разработчикам. Я постарался описать процесс максимально понятным для начинающего ардуинщика языком и собрать в одном месте информацию, которую мне удалось добыть в различных источниках, и проверенную опытным путем. Может быть кому-то эта статья сэкономит пару часов времени.

Удачи в освоении микроконтроллеров!
https://habrahabr.ru/post/247663/