Arduino/CraftDuino и WinAVR — программируем на чистом С


Здесь упоминалось, что 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 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)
WinAVR IDE
Но, получаем сообщение об ошибке, т.к. 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, щёлкаете изменить и через точку с запятой добавляете нужные пути.

WinAVR IDE
Получилось!
А в директории рядом с нашим 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 : Указываем тип МК для программирования. Например, если бы был ATtiny2313, здесь нужно было бы написать: attiny2313. Мы же указываем нашу атмегу 🙂
m8 ATmega8
m16 ATmega16
m32 ATmega32

-c : Указываем тип программатора. Если используется STK500 — пишем stk500 и т.д.

-P : указывается коммуникационный порт, к которому подключён программатор. Это может быть COM1 или LPT1 или даже USB.

-b : Указывается скорость для работы с последовательным портом – нужно для программаторов, работающих через COM-порт – таких как STK500.

-D: Отключаем очистку МК перед прошивкой.

-U :r|w|v:[:format]: Самая важная команда – выполнение прошивки.
— тип памяти МК — flash или eeprom (или hfuse, lfuse, efuse для конфигурации фьюзов МК).
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 : указываем путь до конфигурационного файла avrdude
-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 — программируем на чистом С”»

    • Возможно у Вас WinAVR установлен в директорию, содержащую в своем имени пробелы или скобки

  1. Здравствуйте!
    Не получается. При компиляции выдает ошибку:
    avrblink.c:29: fatal error: opening dependency file .dep/avrblink.o.d: No such file or directory

    В чем может быть дело? На компе Win7

    • Попробуй такой Makefile:

      MCU = atmega168
      FREQUENCY = 16000000
      
      CC = avr-gcc
      CFLAGS = -Os -Wall -pedantic -std=c99 -DF_CPU=$(FREQUENCY)L -mmcu=$(MCU)
      OBJCOPY = avr-objcopy
      AVRSIZE = avr-size
      RM = rm
      
      .PHONY: all clean
      
      .c.o:
      	$(CC) $(CFLAGS) -c -o $@ $<
      
      OBJS = avrblink.o
      COMBINED = avrblink.out
      FIRMWARE = avrblink.hex
      
      all: $(FIRMWARE)
      
      $(FIRMWARE): $(COMBINED)
      	$(OBJCOPY) -O ihex $(COMBINED) $(FIRMWARE)
      
      $(COMBINED): $(OBJS)
      	$(CC) -o $(COMBINED) $(OBJS)
      
      clean:
      	-$(RM) -f $(OBJS) $(COMBINED) $(FIRMWARE)
      

      Немножко пояснений (:

      Переменная MCU — модель микроконтроллера, FREQUENCY — его частота, CC — компилятор, CFLAGS — опции компиляции:

      -Os                     оптимизировать для меньшего размера
      -Wall                   включить все предупреждения
      -pedantic               строго придерживаться стандартов ISO на C и C++,
                              выдавать ошибки при их нарушении
      -std=c99                исходники написаны на C стандарта 1999 года (последний)
      -DF_CPU=$(FREQUENCY)L   (в данном случае будет -DF_CPU=16000000L) это чтобы не писать
                              в каждом исходнике: #define F_CPU 16000000L
      -mmcu=$(MCU)            указываем модель МК

      Правило

      .PHONY: all clean
      

      поясняет утилите make, что all и clean могут быть только именами целей, но не файлов.

      Цель (в мануале по make это называется target)

      .c.o:
      	$(CC) $(CFLAGS) -c -o $@ $<

      указывает, что объектные файлы (.o) получаются из исходников (.c) путём компиляции при помощи компилятора, указанного в переменной CC, с опциями в CFLAGS. Входной файл обозначается $<, выходной — $@. Опция -c указывает, что нужно только сгенерировать объектный файл, больше ничего. Вообще, эту цель указывать необязательно: утилита make знает, как собирать сишные исходники — только укажи компилятор да флаги.
      В переменной OBJS указываешь список объектных файлов. Если у тебя в проекте будет ещё какой-нибудь megafunctions.c, впиши в OBJS объектник megafunctions.o, тогда при команде make у тебя скомпилируется и megafunctions.c
      COMBINED — имя «выходного» файла, получающегося сборкой нескольких объектников.
      FIRMWARE — «прошивка». То, что пригодно для заливки на МК, в нашем случае это hex-файл.

      Первая цель

      all: $(FIRMWARE)

      будет собираться утилитой make по умолчанию, если не указать при вызове других целей. Зависит от цели $(FIRMWARE) (у нас это файл avrblink.hex).

      Следующая цель

      $(FIRMWARE): $(COMBINED)
      	$(OBJCOPY) -O ihex $(COMBINED) $(FIRMWARE)
      

      зависит от цели $(COMBINED) (файл avrblink.out) и вызывает утилиту avr-objcopy для преобразования собранной цели $(COMBINED) в hex-файл $(FIRMWARE) (avrblink.hex).

      Цель

      $(COMBINED): $(OBJS)
      	$(CC) -o $(COMBINED) $(OBJS)

      зависит от $(OBJS) — списка объектных файлов, которые эта цель слинкует в один файл $(COMBINED).
      Цель $(OBJS) соберётся автоматически, т.к. make автоматически вызовет компиляцию .c-файлов в .o-файлы благодаря заданной ранее цели ".c.o".
      Ну а цель clean — это чистка «мусора», т.е. всего, что получается после компиляции: пишешь команду make clean и мусора как не бывало.

      Можешь для пущего счастья ещё добавить какую-нибудь цель upload, загружающую прошивку на МК, типа:

      upload: $(FIRMWARE)
      	avrdude <всякие опции> -U flash:w:$(FIRMWARE)

      тогда можно будет командой make upload собрать проект и тут же его залить на МК. Проект соберётся автоматически, так как мы указали, что цель upload зависит от цели $(FIRMWARE).

    • Вкралась небольшая ошибка, еле обнаружил — цель сборки объектных файлов должна выглядеть так:

      $(COMBINED): $(OBJS)
      	$(CC) $(CFLAGS) -o $(COMBINED) $(OBJS)

      вместо

      $(COMBINED): $(OBJS)
      	$(CC) -o $(COMBINED) $(OBJS)

      Иначе поломается таблица прерываний.

    • Еще раз спасибо за быстрый ответ. Теперь такой вопрос.
      1. Выдергиваю шнур
      2. Зажимаю ресет.
      3. Вставляю шнур.
      4. Нажимаю «Program»
      5. Отпускаю ресет.
      И прошивка нормально заливается. Если просто нажимать «Program» — ArduinoUploader долго тормозит и говорит:

      stk_500_getsync(): not in synk resp=0x00

      Есть ли предположения, как избежать таких танцев с бубном? Интернет не спешит давать ответ:) Он смог пока только научить этому танцу:)

    • Итак. Первый раз после перезагрузки винды работает без бубна. потом только с ресетом ардуины. Достаточно просто нажать на кнопку. Танец сократился после того как я выставил бауд-рейт ком-порта в девайс-манагере на 19200.

      Видимо, ArduinoUploader плохо чистит ком-порт после прошивки. Позже посмотрю исходники.

  2. Та же проблема с windows 7… Попробовал Makefile от burjui:

    MCU = atmega168
    FREQUENCY = 16000000
    CC = avr-gcc
    CFLAGS = -Os -Wall -pedantic -std=c99 -DF_CPU=$(FREQUENCY)L -mmcu=$(MCU)
    OBJCOPY = avr-objcopy
    AVRSIZE = avr-size
    RM = rm
    .PHONY: all clean
    .c.o:
    $(CC) $(CFLAGS) -c -o $@ $<
    OBJS = avrblink.o
    COMBINED = avrblink.out
    FIRMWARE = avrblink.hex
    all: $(FIRMWARE)
    $(FIRMWARE): $(COMBINED)
    $(OBJCOPY) -O ihex $(COMBINED) $(FIRMWARE)
    $(COMBINED): $(OBJS)
    $(CC) $(CFLAGS) -o $(COMBINED) $(OBJS)
    clean:
    -$(RM) -f $(OBJS) $(COMBINED) $(FIRMWARE)

    Output выдал:

    > "make.exe" all
    makefile:10: *** missing separator.  Stop.
    
    > Process Exit Code: 2
    > Time Taken: 00:00
    
    

    Не подскажите, в чем проблема?

    • Всё ясно, в прошлый раз криво скопировал (:

    • Премного благодарен! Все заработало 🙂

    • Используя Ваш makefile попробовал поэкспериментировать с OPT (=0, =s и т.д.) но размер hex файла не изменялся, и всегда составлял 619 байт. Интересно, почему так?
      P.S. прошу прощения, если надоел с вопросами)

    • Ну, видимо, в вашем случае компилятор одинаково оптимизировал код при разных опциях. Ну или вы ошиблись, когда их указывали (:

    • А, да, в Makefile’ах для отступа используется символ табуляции, а не пробелы:

      $(COMBINED): $(OBJS)
      	$(CC)

      Про этот separator make и говорит: перед $(CC) должен быть символ табуляции. В прошлом моём комментарии как-то оказались пробелы — то ли криво скопировал, то ли парсер табуляции превратил в пробелы.

  3. с таким Makefile

    MCU = atmega328p
    FREQUENCY = 16000000
    TARGET = prog
    CC = avr-gcc
    CFLAGS = -Os -Wall -pedantic -std=c99 -DF_CPU=$(FREQUENCY)L -mmcu=$(MCU)
    OBJCOPY = avr-objcopy
    AVRSIZE = avr-size
    RM = rm
    
    .PHONY: all clean
    
    .c.o:
    	$(CC) $(CFLAGS) -c -o $@ $<
    
    OBJS = prog.o
    COMBINED = prog.out
    FIRMWARE = prog.hex
    
    all: $(FIRMWARE)
    
    $(FIRMWARE): $(COMBINED)
    	$(OBJCOPY) -O ihex $(COMBINED) $(FIRMWARE)
    
    $(COMBINED): $(OBJS)
    	$(CC) $(CFLAGS) -o $(COMBINED) $(OBJS)
    
    clean:
    	-$(RM) -f $(OBJS) $(COMBINED) $(FIRMWARE)

    выдает на выходе

    > "make.exe" all
    avr-gcc -Os -Wall -pedantic -std=c99 -DF_CPU=16000000L -mmcu=atmega328p -o prog.out prog.o
    c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr5/crtm328p.o:(.init9+0x0): undefined reference to `main'
    make.exe: *** [prog.out] Error 1
    
    > Process Exit Code: 2
    > Time Taken: 00:00
    

    и создается только файл prog.o
    что я не так делаю?

    • в директории рядом с Makefile нужен prog.c
      например, такой Blink:

      #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 сек.
      
      	}
      }
      
  4. > "make.exe" all
    avr-gcc -Os -Wall -pedantic -std=c99 -DF_CPU=16000000L -mmcu=atmega168 -c -o avrblink.o avrblink.c
    avrblink.c:1: error: stray '\317' in program
    avrblink.c:1: error: stray '\320' in program
    avrblink.c:1: error: stray '\310' in program
    avrblink.c:1: error: stray '\314' in program
    avrblink.c:1: error: stray '\305' in program
    avrblink.c:1: error: stray '\320' in program
    avrblink.c:1: error: stray '\314' in program
    avrblink.c:1: error: stray '\310' in program
    avrblink.c:1: error: stray '\303' in program
    avrblink.c:1: error: stray '\300' in program
    avrblink.c:1: error: stray '\315' in program
    avrblink.c:1: error: stray '\310' in program
    avrblink.c:1: error: stray '\337' in program
    avrblink.c:1: error: stray '\321' in program
    avrblink.c:1: error: stray '\302' in program
    avrblink.c:1: error: stray '\305' in program
    avrblink.c:1: error: stray '\322' in program
    avrblink.c:1: error: stray '\316' in program
    avrblink.c:1: error: stray '\304' in program
    avrblink.c:1: error: stray '\310' in program
    avrblink.c:1: error: stray '\316' in program
    avrblink.c:1: error: stray '\304' in program
    avrblink.c:1: error: stray '\300' in program
    avrblink.c:1: error: stray '\314' in program
    avrblink.c:1: error: stray '\310' in program
    avrblink.c:1: error: expected identifier or '(' before ':' token
    avrblink.c:2: error: stray '\340' in program
    avrblink.c:2: error: stray '\344' in program
    avrblink.c:2: error: stray '\340' in program
    avrblink.c:2: error: stray '\357' in program
    avrblink.c:2: error: stray '\362' in program
    avrblink.c:2: error: stray '\350' in program
    avrblink.c:2: error: stray '\360' in program
    avrblink.c:2: error: stray '\356' in program
    avrblink.c:2: error: stray '\342' in program
    avrblink.c:2: error: stray '\340' in program
    avrblink.c:2: error: stray '\355' in program
    avrblink.c:2: error: stray '\355' in program
    avrblink.c:2: error: stray '\373' in program
    avrblink.c:2: error: stray '\351' in program
    avrblink.c:2: error: stray '\344' in program
    avrblink.c:2: error: stray '\353' in program
    avrblink.c:2: error: stray '\377' in program
    In file included from c:/winavr/lib/gcc/../../avr/include/inttypes.h:37,
                     from c:/winavr/lib/gcc/../../avr/include/avr/sfr_defs.h:126,
                     from c:/winavr/lib/gcc/../../avr/include/avr/io.h:99,
                     from avrblink.c:6:
    c:/winavr/lib/gcc/../../avr/include/stdint.h:159: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int_least8_t'
    c:/winavr/lib/gcc/../../avr/include/stdint.h:213: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int_fast8_t'
    In file included from avrblink.c:7:
    c:/winavr/lib/gcc/../../avr/include/avr/delay.h:36:2: warning: #warning "This file has been moved to <util/delay.h>."
    avrblink.c:8:1: warning: "F_CPU" redefined
    <command-line>: warning: this is the location of the previous definition
    make.exe: *** [avrblink.o] Error 1
    
    
    > Process Exit Code: 2
    > Time Taken: 00:00

    В чем ошибка? На что вообще в этой портянке нужно обращать внимание?

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение