Здесь упоминалось, что Arduino/CraftDuino/Freeduino можно программировать не только на Wiring-е, но и на других языках программирования.
Попробуем разобраться как это можно сделать — написать программу на обычном С/C++.
Для этого воспользуемся компилятором WinAVR.
WinAVR — это интегрированная среда разработки; она включает мощные компиляторы Си и ассемблера, программатор AVRDUDE, отладчик, симулятор и множество других вспомогательных программ и утилит.
Скачать WinAVR можно на странице проекта:
http://sourceforge.net/projects/winavr/
однако, в комплекте Arduino IDE уже идёт WinAVR (\hardware\tools\avr\), поэтому можно воспользоваться им.
Для работы с исходными текстами подойдёт компонент WinAVR – Programmers Notepad (\hardware\tools\avr\pn\pn.exe) — удобный редактор программиста и интегрированная среда разработки (IDE):
Для более подробного знакомства со средой разработки WinAVR рекомендую статьи
Среда разработки WinAVR.
Makefile и компиляция программы.
Возьмём пример из второй статьи и адаптируем его для Arduino:
Создаём файл avrblink.c
/************************************************ ПРИМЕР МИГАНИЯ СВЕТОДИОДАМИ :: MYROBOT.RU , адаптированный RoboCraft.ru для Arduino *************************************************/ #include <avr/io.h> #include <avr/delay.h> #define F_CPU 16000000UL // 16 MHz int main(void) // начало основой программы { DDRD = 0xff; // все выводы порта D сконфигурировать как выходы while (1) { // Бесконечный цикл PORTD = 0xff; // установить "1" на всех линиях порта D _delay_ms(1000);// Ждем 1 сек. PORTD = 0x00; // установить "0" на всех линиях порта D _delay_ms(1000);// Ждем 1 сек. } }
— адаптировали, изменив частоту на 16МГц и время задержки 😉 Однако, как видно в исходнике – сейчас МК мигает всем портом D! Т.е., если посмотреть Arduino Pin Mapping – цифровыми выходами, начиная с digital pin 0 и заканчивая digital pin 7.
В WinAVR исходный текст программы компилируется при помощи утилиты make.exe, которая находится в папке WinAVR\utils\bin. Make.exe контролирует генерацию исполняемых файлов из исходного кода программы. Для управления работой этой утилиты используют make-файлы. Make-файл сообщает компилятору, какие команды запускать, какие файлы компилировать и линковать, какой выходной код генерировать и т. д.
Копируем в директорию с нашим .c-файлом Makefile–образец (\hardware\tools\avr\sample\ Makefile)
и вносим требуемые изменения:
указываем тип микроконтроллера
# MCU name MCU = atmega8 Либо atmega168
Далее указываем частоту
F_CPU = 16000000
название нашего проекта
# Target file name (without extension). TARGET = avrblink
Уровень оптимизации s – можно заменить на 0, чтобы отключить оптимизацию
# Optimization level, can be [0, 1, 2, 3, s]. # 0 = turn off optimization. s = optimize for size. # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) OPT = s
Тип и порт программатора
AVRDUDE_PROGRAMMER = stk500v2 # com1 = serial port. Use lpt1 to connect to parallel port. AVRDUDE_PORT = com1 # programmer connected to serial device
Сохраняем изменения и пробуем скомпилировать (Tools – Make All)
Но, получаем сообщение об ошибке, т.к. Programmers Notepad не знает где искать компилятор и утилиту make.exe
Прописываем пути к нужным директориям:
c:\utils\arduino-0016\hardware\tools\avr\utils\bin\
c:\utils\arduino-0016\hardware\tools\avr\bin\
c:\utils\arduino-0016\hardware\tools\avr\avr\bin\
в переменную среды PATH, перезагружаемся и пробуем снова
В ОС Windows это делается через Мой Компьютер — Свойства — Дополнительно — Переменные среды. Выбираете PATH, щёлкаете изменить и через точку с запятой добавляете нужные пути.
Получилось!
А в директории рядом с нашим avrblink.c и Makefile появилось много интересного:
— .dep/avrblink.o.d
— avrblink.eep
— avrblink.elf
— avrblink.hex
— avrblink.lss
— avrblink.lst
— avrblink.map
— avrblink.o
— avrblink.sym
Самый важный из этих файлов — это avrblink.hex. В нем хранится шестнадцатиричный код для загрузки в память программ (Flash ROM) микроконтроллера.
:1000000012C02CC02BC02AC029C028C027C026C0BF :1000100025C024C023C022C021C020C01FC01EC0D4 :100020001DC01CC01BC011241FBECFE5D4E0DEBF25 :10003000CDBF10E0A0E6B0E0EEE8F0E002C0059031 :100040000D92A036B107D9F710E0A0E6B0E001C0EC :100050001D92A036B107E1F702D017C0D1CF8FEFC4 :1000600081BB4FEF20E931E042BB80E197E2F9012B :100070003197F1F70197D9F712BA80E197E2F901C8 :0E0080003197F1F70197D9F7EFCFF894FFCF42 :00000001FF
А avrblink.eep — хранит шестнадцатиричный код для загрузки в энергонезависимую память данных (EEPROM).
Попробуем загрузить наш .hex в наш proteus-кий простейший симулятор ардуины
Мигает 🙂
Однако, нужно привести нашу программу ближе к стандартному Blink-у и помигать одним встроенным светодиодом на digital pin13. Как видим по схеме или по Arduino Pin Mapping – это пятая линия порта B.
Читаем крайне познавательную статью
AVR GCC :: Управление портами микроконтроллера AVR.
и вносим нужные изменения в нашу программу:
/************************************************ ПРИМЕР МИГАНИЯ СВЕТОДИОДОМ от MYROBOT.RU, адаптированный RoboCraft.ru для Arduino данный пример повторяет стандартный скетч Blink *************************************************/ #include <avr/io.h> #include <avr/delay.h> #define F_CPU 16000000UL // 16 MHz int main(void) // начало основой программы { DDRB = 0x20; // 0b00100000 конфигурируем 5-ю линию порта B, как выход - остальные - вход while (1) { // Бесконечный цикл PORTB |= _BV(PC5); // установить "1" на линии 5 порта B (digital pin 13) _delay_ms(1000); // Ждем 1 сек. PORTB &= ~_BV(PC5); // установить "0" на линии 5 порта B _delay_ms(1000); // Ждем 1 сек. } }
UPD — обновлённая версия для новых версий компилятора:
#include <avr/io.h> #include <util/delay.h> int main(void) // начало основой программы { DDRB |= _BV(DDB5); // конфигурируем 5-ю линию порта B, как выход - остальные - вход while (1) { // Бесконечный цикл PORTB |= _BV(DDB5); // установить "1" на линии 5 порта B (digital pin 13) _delay_ms(1000); // Ждём 1 сек. PORTB &= ~_BV(DDB5); // установить "0" на линии 5 порта B _delay_ms(1000); // Ждём 1 сек. } }
Компилируем, загружаем в протеус – работает!
Сравним размеры файлов 🙂
Ардуиновский Blink.hex весит 2031 байт
Наш hex при оптимизации по размеру (OPT = s) по размеру весит 410 байт
а с отключённой оптимизацией (OPT = 0) все 3184 байта!
Теперь осталось разобраться как же в реальности прошить наш .hex в ардуину 🙂
Например, можно воспользоваться каким-нибудь программатором 🙂
Однако, у нас ведь есть загрузчик и поэтому можем просто воспользоваться родным приёмом ардуины – самопрограммированием МК.
В любом случае, нам понадобится воспользоваться утилитой AVRDUDE, которая идёт в составе WinAVR и находится внутри Arduino IDE (\hardware\tools\avr\)
AVRDUDE позволяет загружать программы и данные в память микроконтроллера, а также считывать их оттуда. AVRDUDE использует SPI-интерфейс. Существуют версии для Windows и Linux. Первоначальный код был написан Брайеном Дином (Brian S. Dean) и имел название avrprog.
При использвании ардуиновского «параллельного программатора» или популярных для LPT – пяти проводков – нужная дополнительная настройка:
В Windows 2000 и Windows XP запрещена прямая работа с параллельным (LPT) портом, поэтому для нормальной работы AVRDUDE необходимо установить драйвер giveio.sys. Для установки этого драйвера зайдите в папку WinAVR\bin и запустите файл install_giveio.bat (удалить драйвер из системы можно, запустив файл remove_giveio.bat).
В Windows 98 никаких специальных настроек не требуется.
AVRDUDE — консольная программа и для её работы ей нужно передавать кучу параметров, но для упрощения задачи, уже есть готовая программа — ArduinoUpload, которая написана на C# и которая как раз и делает – то что нам нужно — загружает в ардуину .hex-файл через утилиту avrdude.
остаётся выбрать наш .hex-файл, COM-порт к которому подключена ардуина и указать путь до avrdude (\hardware\tools\avr\bin\avrdude.exe)
Как видим, всё что делает программа — это формирует команду вида:
avrdude -F -v -pm168 -cstk500v1 -P\\.\COM4 -b19200 -D -Uflash:w:"file.hex":i
разберёмся, что значат все эти параметры:
-F: Игнорировать проверку соединения с МК. Разумеется, такая проверка желательна – поэтому использование этого флага стоит избегать.
-v: так называемый «многословный» (verbose) вывод – полезно для контроля и отладки.
-p
m8 ATmega8
m16 ATmega16
m32 ATmega32
-c
-P
-b
-D: Отключаем очистку МК перед прошивкой.
-U
r|w|v – флаги определяют, что мы хотим сделать:
r (read — считать)
w (write — записать)
v (verify — проверить).
[:format] флаг формата данных. Здесь всегда используется формат «Intel Hex», поэтому стоит i
Таким образом, командой -Uflash:w:»file.hex»:I – мы записываем файл file.hex в FLASH-память МК. Если нам потребуется считать eeprom-память в файл «eedump.hex» – мы напишем -Ueeprom:r:eedump.hex:i
Дополнительные параметры AVRDUDE:
-C
-e: очистка МК
-n: ничего не записывать в МК. Защита, чтобы не отправить в МК ничего лишнего 🙂
-u: указывает, что хотим модифицировать фьюзы МК.
-t: терминальный режим
-q: в противоположность -v – это «тихий» режим – меньше слов – больше дела 🙂
список параметров с их кратким описанием можно получить просто запустив avrdude без параметров или с параметром -?
А более подробную документацию можно найти здесь(\hardware\tools\avr\doc\avrdude\avrdude.pdf).
Ну что же – пробуем прошить. Жму Reset на плате и сразу кнопку “Program”
Ошибка!
AVRDUDE пишет, что не находит своего конфигурационного файла 🙁
Хм… попробуем ему помочь – дописываем в конец строчку:
-C"c:\utils\arduino-0016\hardware\tools\avr\etc\avrdude.conf"
И снова перезагружаю плату и жму “Program”.
Ура! Получилось! Пойду допишу об этом нюансе на сайт ардуины 😉
Вот так – научились загружать в ардуину другие программы, которые можно писать хоть на ассемблере! 🙂
А так же теперь становится понятно, насколько Arduino IDE упрощает процесс программирования микроконтроллеров! 🙂
Приложение:
Скетч WinAVR-кого Blink-а, перенесённый в Arduino IDE
#include <avr/io.h> #include <avr/delay.h> void setup() { DDRB = 0x20; // 0b00100000 конфигурируем 5-ю линию порта B, как выход - остальные - вход } void loop() { PORTB |= _BV(PC5); // установить "1" на линии 5 порта B (digital pin 13) _delay_ms(1000); // Ждем 1 сек. PORTB &= ~_BV(PC5); // установить "0" на линии 5 порта B _delay_ms(1000); // Ждем 1 сек. }
далее: Переходим от Arduino к программированию ATtiny13 на C
Ссылки
http://sourceforge.net/projects/winavr/
СРЕДА РАЗРАБОТКИ WinAVR
MAKEFILE И КОМПИЛЯЦИЯ ПРОГРАММЫ
ПРОСТОЙ ПРОГРАММАТОР AVR :: AVRDUDE
http://www.arduino.cc/playground/Code/ArduinoUpload (архив с программой, исходники)
AVR Tutorial — Starting out with avrdude
По теме
Делаем ISP-программатор из Arduino
Про фьюзы
Программаторы
23 комментария на «“Arduino/CraftDuino и WinAVR — программируем на чистом С”»
> Получилось!
У меня ничего не получилось. arduino IDE 18 версии. 17 ошибок в том числе синтаксные. ЧЯДНТ?
Причем в makefile
Возможно у Вас WinAVR установлен в директорию, содержащую в своем имени пробелы или скобки
Здравствуйте!
Не получается. При компиляции выдает ошибку:
avrblink.c:29: fatal error: opening dependency file .dep/avrblink.o.d: No such file or directory
В чем может быть дело? На компе Win7
Попробуй такой Makefile:
Немножко пояснений (:
Переменная MCU — модель микроконтроллера, FREQUENCY — его частота, CC — компилятор, CFLAGS — опции компиляции:
Правило
поясняет утилите make, что all и clean могут быть только именами целей, но не файлов.
Цель (в мануале по make это называется target)
указывает, что объектные файлы (.o) получаются из исходников (.c) путём компиляции при помощи компилятора, указанного в переменной CC, с опциями в CFLAGS. Входной файл обозначается $<, выходной — $@. Опция -c указывает, что нужно только сгенерировать объектный файл, больше ничего. Вообще, эту цель указывать необязательно: утилита make знает, как собирать сишные исходники — только укажи компилятор да флаги.
В переменной OBJS указываешь список объектных файлов. Если у тебя в проекте будет ещё какой-нибудь megafunctions.c, впиши в OBJS объектник megafunctions.o, тогда при команде make у тебя скомпилируется и megafunctions.c
COMBINED — имя «выходного» файла, получающегося сборкой нескольких объектников.
FIRMWARE — «прошивка». То, что пригодно для заливки на МК, в нашем случае это hex-файл.
Первая цель
будет собираться утилитой make по умолчанию, если не указать при вызове других целей. Зависит от цели $(FIRMWARE) (у нас это файл avrblink.hex).
Следующая цель
зависит от цели $(COMBINED) (файл avrblink.out) и вызывает утилиту avr-objcopy для преобразования собранной цели $(COMBINED) в hex-файл $(FIRMWARE) (avrblink.hex).
Цель
зависит от $(OBJS) — списка объектных файлов, которые эта цель слинкует в один файл $(COMBINED).
Цель $(OBJS) соберётся автоматически, т.к. make автоматически вызовет компиляцию .c-файлов в .o-файлы благодаря заданной ранее цели ".c.o".
Ну а цель clean — это чистка «мусора», т.е. всего, что получается после компиляции: пишешь команду make clean и мусора как не бывало.
Можешь для пущего счастья ещё добавить какую-нибудь цель upload, загружающую прошивку на МК, типа:
тогда можно будет командой make upload собрать проект и тут же его залить на МК. Проект соберётся автоматически, так как мы указали, что цель upload зависит от цели $(FIRMWARE).
Вкралась небольшая ошибка, еле обнаружил — цель сборки объектных файлов должна выглядеть так:
вместо
Иначе поломается таблица прерываний.
ArduinoUpload — битая ссылка. скиньте дистр плиз
в конце статьи в разделе ссылки 😉
Блин, ребята, я вас обожаю.
Еще раз спасибо за быстрый ответ. Теперь такой вопрос.
1. Выдергиваю шнур
2. Зажимаю ресет.
3. Вставляю шнур.
4. Нажимаю «Program»
5. Отпускаю ресет.
И прошивка нормально заливается. Если просто нажимать «Program» — ArduinoUploader долго тормозит и говорит:
stk_500_getsync(): not in synk resp=0x00
Есть ли предположения, как избежать таких танцев с бубном? Интернет не спешит давать ответ:) Он смог пока только научить этому танцу:)
Итак. Первый раз после перезагрузки винды работает без бубна. потом только с ресетом ардуины. Достаточно просто нажать на кнопку. Танец сократился после того как я выставил бауд-рейт ком-порта в девайс-манагере на 19200.
Видимо, ArduinoUploader плохо чистит ком-порт после прошивки. Позже посмотрю исходники.
вот эту штуковину откуда брать _delay_ms(1000); ???
Разобрался, забыл закрыть комментарий:(
Та же проблема с windows 7… Попробовал Makefile от burjui:
Output выдал:
Не подскажите, в чем проблема?
Всё ясно, в прошлый раз криво скопировал (:
В общем, Makefile должен быть примернотаким .
Премного благодарен! Все заработало 🙂
Используя Ваш makefile попробовал поэкспериментировать с OPT (=0, =s и т.д.) но размер hex файла не изменялся, и всегда составлял 619 байт. Интересно, почему так?
P.S. прошу прощения, если надоел с вопросами)
Ну, видимо, в вашем случае компилятор одинаково оптимизировал код при разных опциях. Ну или вы ошиблись, когда их указывали (:
А, да, в Makefile’ах для отступа используется символ табуляции, а не пробелы:
Про этот separator make и говорит: перед $(CC) должен быть символ табуляции. В прошлом моём комментарии как-то оказались пробелы — то ли криво скопировал, то ли парсер табуляции превратил в пробелы.
с таким Makefile
выдает на выходе
и создается только файл prog.o
что я не так делаю?
в директории рядом с Makefile нужен prog.c
например, такой Blink:
В чем ошибка? На что вообще в этой портянке нужно обращать внимание?