====== Работа с микроконтроллерами: прошивка программатором и чистый «Си» ====== В этой статье я расскажу о том, как программировать микроконтроллеры без использования Arduino. Мы будем использовать программатор AvrISP STK500 для программирования контроллера ATtiny84. ===== Нам понадобится ===== {{ :программирование:hardcore2-avr-list3.jpg? |}} * [[amp>product/avrisp-stk500-programmer|Программатор AvrISP STK500]] * [[amp>product/led-5mm|Светодиоды]] * [[amp>product/resistor|Резисторы]] * [[amp>product/wire-mm|Провода «папа-папа»]] * [[amp>product/avr-attiny84|Микроконтроллер ATtiny84]] * [[amp>|Клеммник]] * [[amp>|Батарейка «Крона»]] * [[amp>|Преобразователь напряжения]] ===== Подключаем питание ===== Arduino мы не используем, поэтому обо всем нам придется думать самостоятельно. И первое, с чем необходимо разобраться --- питание. Мы будем использовать преобразователь L7805, обладающей следующими характеристиками: * Выходной ток до 1.5 А * Выходное напряжение — ровные 5 В * Защита от перегрева * Защита от короткого замыкания Теперь нам надо узнать схему подключения этого преобразователя. Ее мы найдем на странице 3 [[http://files.amperka.ru/datasheets/l78xx.pdf|даташита]]. {{ :программирование:hardcore2-l7805-circuit.jpg? |}} Помимо самого преобразователя, мы видим еще 2 конденсатора --- входной Сi и выходной Сo. Входной конденсатор необходим для того, чтобы сгладить пульсации на входе в случае удаленности L7805 от источника. В нашем случае длина соединительных проводов не будет превышать 15 см, поэтому входного конденсатора у нас не будет. Зато будет выходной, поскольку мы хотим «кормить» наш контроллер стабильным питанием. ==== Распиновка ==== Необходимо знать назначение ножек преобразователя. Это описано на 2-й странице даташита. {{ :программирование:hardcore2-l7805-pinout.jpg? |}} ==== Схема ==== С учетом всего вышеописанного, получается схема для организации питания. {{ :программирование:hardcore2-l7805-connected2.jpg? |}} ===== Программатор ===== В качестве программатора мы использовали AvrISP STK500 от Seeed Studio. Для его работы под Windows и Mac OS необходимы драйверы. Их можно скачать с [[http://prolificusa.com/pl-2303hx-drivers/|официального сайта]]. Пользователям Linux устанавливать ничего не нужно — программатор будет сразу готов к работе. ==== Подключение к контроллеру ==== Распиновка разъема программатора такова: {{:программирование:avr_isp.jpg?nolink&}} **Важно!** Это распиновка разъема программатора, если смотреть на него сверху (отверстиями от себя). Не перепутайте! {{ :программирование:hardcore2-connection3.jpg? |}} Разъем программатора необходимо подключить к микроконтроллеру. Можно использовать как 10-пиновый разъём, так и 6-пиновый. Без разницы. Соединим проводами соответствующие пины, т.е: | ^ 10-пиновый ICSP ^ ATtiny84 ^ ^ Reset | 5 | 4 | ^ MOSI | 1 | 7 | ^ MISO | 9 | 8 | ^ SCK | 7 | 9 | ===== Прошивка ===== Напишем код прошивки на чистом «C», которая заставит светодиод мигать. Использование ШИМ-сигналов и считывание аналоговых сигналов на чистом «C» не так тривиальна, и может являться темой отдельной статьи, поэтому остановимся пока на простейшем примере. #include #include int main(void) { // номер пина 2 в порту А -- на выход DDRA = 1 << 2; // основной цикл while (1==1) { _delay_ms(500); // задержка 500 мс PORTA ^= 1 << 2; // инвертирование значения на выводе } return 0; } После скетчей Arduino, код малопонятен, правда? Ничего, сейчас я объясню, что да как. В первых двух строчках мы подключаем необходимые библиотеки, чтобы воспользоваться такими штуками, как ''DDRA'', ''PORTA'', ''_delay_ms''. Что же такое ''DDRA''? Это регистр микроконтроллера, управляющий направлением работы порта А. Он содержит в себе 8 бит. Если установить какой-то бит в 1, то пин с соответствующим номером станет выходом. ''PORTA'' --- тоже регистр, но он содержит в себе данные порта А. Если мы хотим на вывод номер 2 записать логическую единицу, то мы должны поместить 1 в соответсвующий бит регистра. А ''_delay_ms'' --- функция задержки. Исходя из этого можно составить таблицу соответствия: | ^ Arduino ^ C ^ ^ Направление | ''pinMode(led, OUTPUT);'' | ''DDRA = 1 %%<<%% 2;'' | ^ Значение | ''digitalWrite(led, HIGH);''| ''PORTA = 1 %%<<%% 2;'' | ^ Задержка | ''delay(1000); '' | ''_delay_ms(50); '' | Однако, самым важным различием кода является то, что в программе на С нет разделений функций ''setup'' и ''loop''. За все это отвечает функция ''int main(void)''. И она выполняется всего 1 раз! А мы хотим, чтобы наш светодиод моргал не один раз, а постоянно. Как раз для этого и используется бесконечный цикл ''while (1==1)''. Поэтому легко сделать вывод, что этот цикл и есть аналог функции ''loop()'' в Arduino. А то, что до него --- аналог функции ''setup()''. Далее начинается самое интересное. Нам нужно скомпилировать и загрузить прошивку. Однако, в зависимости от вашей операционной системы, методика будет различаться. ==== Mac OS X ==== Первым делом необходимо [[http://www.obdev.at/products/crosspack/download.html|скачать]] и установить CrossPack for AVR Development. Это даст нам все необходимые инструменты. CrossPack состоит из двух частей. - AVR Libc --- a C library for GCC on AVR microcontrollers - AVRDUDE --- AVR Downloader/Uploader Первая нам нужна для написания кода и создания файла прошивки, а вторая --- для заливки прошивки в контроллер. Проект создается в три шага. - Запустите терминал - Перейдите в нем в нужную папку - Создайте проект с помощью команды ''avr-project'' $ mkdir ~/AVR $ cd AVR $ avr-project firstProject Using template: /usr/local/CrossPack-AVR-20130212/etc/templates/TemplateProject В результате будет создано следующее дерево файлов. $ tree . |-- firmware | |-- main.c | `-- Makefile `-- firstProject.xcodeproj 1 directory, 3 files На данном этапе нас интересует содержимое файла ''Makefile''. В нем содержится информация о том, что вообще мы используем: какой контроллер, программатор. Это все описывается в строках с 20 по 24: DEVICE = atmega8 CLOCK = 8000000 PROGRAMMER = #-c stk500v2 -P avrdoper OBJECTS = main.o FUSES = -U hfuse:w:0xd9:m -U lfuse:w:0x24:m Пройдемся по строкам: - ''DEVICE'' содержит в себе название контроллера, который мы программируем - ''CLOCK'' --- частота работы - ''PROGRAMMER'' --- используемый программатор - ''OBJECTS'' --- какие объектные файлы будут сгененрированы - ''FUSES'' --- конфигурация fuse-битов в микроконтроллере Это автосгенерированный make-файл, поэтому нам необходимо вручную его подправить. Править будем строку ''DEVICE'' у нас же микроконтроллер ''attiny84'' и строку ''FUSES''. А вот с ней все сложнее. Fuse-биты, или просто <<фьюзы>> --- два (иногда три) особых байта, в которых содержится фундаментальая конфигурация работы контроллера. Очень важно правильно их задать. **Внимание! Задание неверных fuse-битов может привезти к тому, что микроконтроллер перестанет работать и вернуть его к нормальной жизни может быть либо очень сложно либо невозможно!** Воспользеумся сайтом [[http://www.frank-zhao.com/fusecalc/fusecalc.php?chip=attiny84&LOW=E2&HIGH=DF&EXTENDED=FF&LOCKBIT=FF|AVR Fuse Calcuator]]. Сначала из выпадающего списка выберем нужный нам контроллер (ATtiny84). {{ :программирование:hardcore2-avr-fuse4.png? |}} И затем укажем необходимые опции, которые нам нужны. Сейчас для нас важны 2 вещи: сохранение возможности прошивать контроллер через SPI и сохранение его работоспособности без внешнего резонатора, поэтому выбираем соответствующие пункты, а остальные оставляем по умолчанию. {{ :программирование:hardcore2-avr-fuse6.png? |}} Видим, как поменялись сгенерированные значения. {{ :программирование:hardcore2-avr-fuse7.png?700 |}} Внесем изменения в Makefile. DEVICE = attiny84 CLOCK = 8000000 PROGRAMMER = -c stk500v2 -P /dev/tty.usbserial OBJECTS = main.o FUSES = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m === Прошивка === Она происходит в 2 этапа. Сначала необходимо перейти в папку ''firmware'' и выполнить команду ''make''. Если ошибок нет, то результат выполнения команды будет таким: $ make avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=attiny84 -c main.c -o main.o avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=attiny84 -o main.elf main.o rm -f main.hex avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size --format=avr --mcu=attiny84 main.elf AVR Memory Usage ---------------- Device: attiny84 Program: 126 bytes (1.5% Full) (.text + .data + .bootloader) Data: 0 bytes (0.0% Full) (.data + .bss + .noinit) Эта команда сделает из нашего исходника ''main.c'' файл, пригодный для заливки в контроллер --- ''main.hex''. Второй этап --- как раз заливка прошивки. Делается это с помощью команды ''make flash''. Ее нормальный вывод выглядит следующим образом: $ make flash avrdude -c stk500v2 -P /dev/tty.usbserial -p attiny84 -U flash:w:main.hex:i avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e930c avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: reading input file "main.hex" avrdude: writing flash (126 bytes): Writing | ################################################## | 100% 0.10s avrdude: 126 bytes of flash written avrdude: verifying flash memory against main.hex: avrdude: load data flash data from input file main.hex: avrdude: input file main.hex contains 126 bytes avrdude: reading on-chip flash data: Reading | ################################################## | 100% 0.08s avrdude: verifying ... avrdude: 126 bytes of flash verified avrdude: safemode: Fuses OK avrdude done. Thank you. Все, прошивка контроллера завершена. ==== Windows ==== Здесь все проще. Первым делом необходимо скачать и уствновить среду разработки для AVR --- [[http://www.atmel.com/System/BaseForm.aspx?target=tcm:26-17924|Atmel AVR Studio 4]]. А вторым --- [[http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx|Atmel AVR Toolchain]]. После запуска среды, необходимо создать новый проект. {{ :программирование:hardcore2-avrstudio-project.png? |}} Затем указать имя, расположение и то, что мы хотим использовать С (''GCC''). {{ :программирование:hardcore2-avrstudio-project2.png? |}} Третий шаг --- настройка отладчика. {{ :программирование:hardcore2-avrstudio-project3.png? |}} На этом все, проект готов к использованию. Теперь необходимо написать и сохранить исходник, который мы уже обсудили. В результате общий вид среды разработки выглядит вот так: {{ :программирование:hardcore2-avrstudio-main.png?700 |}} Теперь необходимо подключиться к программатору. Делается это с помощью нажатия на кнопку ''con''. {{ :программирование:hardcore2-avrstudio-connection1.png? |}} В качестве ''Platform'' выбираем ''STK500'', а в ''Port'' --- ''Auto''. Затем нажимаем Connect. {{ :программирование:hardcore2-avrstudio-connection2.png? |}} Если все правильно, то в открывшемся окне выбираем вкладку ''Main'' и нажимаем в ней на кнопку ''Read Signature''. {{ :программирование:hardcore2-avrstudio-signature.png? |}} Строка ''Reading signature from device .. 0x1E, 0x93, 0x0C .. OK!'' говорит о том, что все хорошо и сигнатура успешно прочиталась. Сигнатура — это своего рода позывной микроконтроллера, которым он сообщает собственную модель. Это окно нельзя закрывать, иначе соединение с программатором будет потеряно. Просто сверните его. Теперь нажмем ''Build -> Build''. Это заставит программу скомпилироваться. Прошьем контроллер с помощью кнопки ''Write Flash Memory Using Current Settings'' — это заставит скомпилированную программу загрузиться в память микроконтроллера. {{ :программирование:hardcore2-avrstudio-flash.png? |}} ===== Заключение ===== Мы собрали простейшее устройство мигалку, но сделали это на низком уровне. С использованием программатора и «продвинутой» среды разработки, а не Arduino. {{ :программирование:hardcore2-result2.jpg?nolink& |}} Разобравшись в премудростях программирования микроконтроллеров на чистом «Си», вы сможете выжимать из них максимум возможности, затрачивая при этом минимум места и денег.