Программирование Arduino даёт не только огромный простор для фантазии и возможностей, но, как и любой фреймворк, одновременно навязывает свой стиль и ограничивает возможности.
Поэтому, если чувствуется, что Arduino становится тесноват — можно не только перейти на 32-битные контроллеры (например, STM32), но и попробовать более низкоуровневое программирование контроллеров.
Уходя ближе «к железу» — программировать придётся на более близком к железу уровне — и если это не ассемблер, то уж язык программирования Си — точно.
Пример подобного программирования уже приводился в статье Arduino/CraftDuino и WinAVR — программируем на чистом С.
У такого стандартного программирования микроконтроллеров есть существенное преимущество перед использованием Arduino-вских скетчей.
Однако, за низкоуровневый полный контроль и возможность использовать все ресурсы микроконтроллера, приходится расплачиваться долгим и внимательным изучением документации (datasheet-а) на микроконтроллер.
Т.е., если у вас ещё не было опыта работы с конкретным микроконтроллером — то вместо быстренького набрасывания скетча для решения своей задачи — вам придётся потратить дополнительное время на изучение мат. части.
Разумеется, не всегда это может быть оправдано и если задачу нужно и можно быстро решить при помощи Arduino — то почему бы и нет?
Однако, если решение задачи на Arduino невозможно, то придётся потратить время на получение ценных опыта и знаний, которые помогут открыть все возможности, которые под силу микроконтроллеру.
Для примера, возьмём меленький, простой и дешёвый контроллер ATtiny13.
ATtiny13
8-битный AVR микроконтроллер с 1 КБ программируемой Flash памяти
— RISC архитектура
— 120 команд, (большинство выполняется за один такт)
— 32 8-битных регистра общего применения
— 1 КБ программируемой Flash памяти программы
— 64 байта EEPROM памяти данных, (до 100 000 циклов записи/стирания)
— 64 байта SRAM памяти (статическое ОЗУ)
— Один 8-разрядный таймер/счётчик с отдельным предделителем и два ШИМ канала
— 4-канальный 10-битный АЦП со встроенным ИОН
— Программируемый сторожевой таймер (watchdog) со встроенным генератором
— Встроенный аналоговый компаратор
— Внутрисистемное программирование через SPI порт
— Внешние и внутренние источники прерывания
Корпусное исполнение:
— 8-выводные PDIP и SOIC корпуса: 6 программируемых линий ввода-вывода
Диапазон напряжения питания, частота:
1.8 – 5.5В (для ATtiny13V) — до 10МГц
2.7 – 5.5В (для ATtiny13) — до 20МГц
Выводы микроконтроллера ATtiny13:
Документация на ATtiny13:
Как видим, микросхема микроконтроллера — маленькая — всего 8 ножек.
Чтобы заставить её работать — нужно просто воткнуть её в макетную плату, подтянуть RESET (первый пин — на схеме обозначается — PB5) к шине питания через 10-килоомный резистор и подать питание — например, 5V снятые с пинов питания контроллера Arduino / CraftDuino.
Разумеется, желательно, ещё повесить конденсатор в 0.1 мкФ между шинами питания.
Подключение ATtiny13 через SPI к CraftDuino
В статье Делаем ISP-программатор из Arduino, уже подробно расписано как нужно подключить микроконтроллер ATtiny13 к контроллеру Arduino или CraftDuino, чтобы его можно было программировать через выводы микросхемы FT232RL используя режим bit-bang (режим управления отдельными выводам микросхемы). Поэтому сразу переходим к софтовой части.
Atmel Studio
Раз решили программировать «по-взрослому», то и среда разработки нужна «взрослая».
Идём на сайт Atmel-a, и скачиваем свежую версию Atmel Studio.
Atmel Studio — (наследница AVR Studio) — это бесплатная среда разработки для микроконтроллеров Atmel.
Сама IDE должна быть знакома, т.к. используется оболочка от Microsoft Visual Studio, однако следует обратить внимание, что в качестве компилятора используется GCC.
После установки, на рабочем столе появится ярлык с симпатичной красной божьей коровкой. Запускаем IDE и привычным образом, быстренько создаём проект.
File -> New -> Project…
Выбираем С/С++ и GCC C Executable Project, пишем имя проекта, например, blink 🙂
Затем, среда предложит выбрать тип используемого микроконтроллера — выбираем ATtiny13.
Всё — шаблонный файл уже создан и можно начинать программировать:
Предлагаемый шаблон программы — напоминает что-то знакомое:
#include <avr/io.h> int main(void) { while(1) { //TODO:: Please write your application code } }
Соответствие функций Arduino на Си
Описание работы портов микроконтроллера и используемых для насткройки и работы регистров, очень подробно приводится в документации на микроконтроллер — ATtiny13 datasheet.
Как увидим далее, конфигурирование и работа с портами сводится к установке соответствующих битов в нужных регистрах микроконтроллера.
Если вы уже имели дело с установкой/проверкой/очисткой битов (работа с битовыми масками), то вам будет проще разобраться в происходящем.
Но, на всякий случай, напомню:
чтобы установить бит N — нужно выполнить побитовое ИЛИ с числом, где этот бит установлен (чтобы получить такое число — мы побитово сдвигаем влево единицу на заданное число позиций).
Соответственно, чтобы сбросить бит N — нужно выполнить побитовое И с числом в котором установлены все биты кроме заданного (чтобы получить такое «интвертированное число» — мы сначала получаем число в котором бит установлен, а потом применяем к нему операцию побитового НЕ).
value |= 1 << N; // установить бит N value &= ~(1 << N); // сбросить бит N
Так как процедура установки бита встречается чрезвычайно часто - для неё даже есть удобный макрос
#define _BV(bit) (1 << (bit))
, который рекомендуется к использованию.
Для простоты понимания Си-шных методов работы, сопоставим им функции Arduino.
Базовые функции управления портами (см. datasheet стр. 48):
// устанавливаем вывод 4 вывод порта B (PB4) как выход DDRB |= (1 << PB4); // pinMode(PB4, OUTPUT); // устанавливаем вывод PB4 как вход DDRB &= ~(1 << PB4); // pinMode(PB4, INPUT); // устанавливаем высокий уровень на выводе PB4 PORTB |= (1 << PB4); // digitalWrite(PB4, HIGH); // устанавливаем низкий уровень на выводе PB4 PORTB &= ~(1 << PB4); // digitalWrite(PB4, LOW); // Чтение состояния(лог. 1) на порту ввода - вывода (4 вывод порта B): if(PINB & (1 << PINB4)) // if (digitalRead(4) == HIGH) { ... } // Чтение состояния(лог. 0) на порту ввода-вывода (4 вывод порта B): if(!(PINB & (1 << PINB4))) // if(digitalRead(4) == LOW) { ... }
В принципе, хотя у ATtiny13 всего 1 килобайт флеша на котором сильно не разгуляешься ,но даже для этой крохи частично реализован Arduino-вский фреймворк - Core13.
В нём есть реализации для:
map() random() randomSeed() millis() micros() delay() delayMicroseconds() * analogRead() analogWrite() pinMode() digitalRead() digitalWrite()
Подробнее про использование Core13 можно прочитать здесь: Прошивка и программирование ATtiny13 при помощи Arduino.
Но даже если использовать Arduino IDE не собираетесь - взглянуть на код всё равно стоит, чтобы проверить как работает и что скрывается за реализацией функций Arduino:
Реализация функций digitalWrite() и digitalRead() из Core13 (core13_022_arduino_1_6)
void digitalWrite(uint8_t pin, uint8_t val){ if(pin > 5 || pin < 0){return;} if(pin<2){turnOffPWM(pin);} //If its a PWM pin, make sure the PWM is off if(!val){ PORTB &= ~_BV(pin); } else { PORTB |= _BV(pin); } } uint8_t digitalRead(uint8_t pin){ if(pin > 5 || pin < 0){return 0;} if(pin < 2) turnOffPWM(pin); //If its PWM pin, makes sure the PWM is off return !!(PINB & _BV(pin)); }
Даже здесь используется много проверок, что разумеется даёт "защиту от дурака", но и является причиной, почему при использовании Arduino-вских функций производительность кода будет ниже.
Частота работы микроконтроллера
По-умолчанию, микроконтроллер ATtiny13 работает на частоте 1.2 МГц - определяется фьюз-битами (так называются специальные конфигурационные биты, находящиеся в специальных ячейках памяти и отвечающие за параметры конфигурации всего МК).
Младший фьюз-байт lfuse = 0x6A
Старший фьюз-байт hfuse = 0xFF
Посмотреть, что означают эти параметры можно в удобном калькуляторе фьюзов для AVR - AVR Fuse Calculator.
В калькуляторе, можно увидеть, что меняя значение младшего фьюз-байта с 0x6A на 0x7A - мы получим работу микроконтроллера на частоте 9.6 МГц за счёт отключения делителя тактового сигнала на 8 (CKDIV8).
9.6 МГц / 8 = 1.2 МГц.
Посмотреть текущие значения фьзов можно при помощи avrdude, командой:
avrdude -C avrdude.conf -c ftbb -P ft0 -B 9600 -p attiny13 -U lfuse:r:low_fuse_val.hex:h -U hfuse:r:high_fuse_val.hex:h
- получим два файла - low_fuse_val.hex и high_fuse_val.hex с шестнацетиричным значением соответствующих фьюзов.
Blink для ATtiny13
Теперь, зная частоту работы контроллера и базовые методы работы с портами, можем написать микроконтроллерный Hello World - а именно - Arduino-вский - Blink:
// 1.2 MHz (default) built in resonator #define F_CPU 1200000UL #include <avr/io.h> #include <util/delay.h> #define LED_BIT _BV(PB4) int main() { DDRB |= LED_BIT; // OUTPUT while (1) { PORTB |= LED_BIT; // HIGH _delay_ms(1000); PORTB &= ~LED_BIT; // LOW _delay_ms(1000); } }
Выбираем тип сборки - Release и жмём F7 для сборки проекта (Build -> Build Solution).
Чтобы проверить работу программы - подключаем к третьей ножке (PB4) светодиод с токоограничительным резистором:
Прошивка МК ATtiny13
Остаётся прошить наш микроконтроллер.
Можно взять готовый hex-файл из папки проекта и используя avrdude, прошить МК командой:
avrdude -C avrdude.conf -c ftbb -P ft0 -B 9600 -p attiny13 -U flash:w:blink.hex
А можно, для удобства прошивки, соответствующим образом настроить Atmel Studio.
Настройка Atmel Studio для прошивки МК ATtiny13 через avrdude
Настроить Atmel Studio для прошивки МК ATtiny13 через avrdude, очень просто.
Идём в меню
Tools -> External Tools
И добавляем нашу тулзу - avrdude:
Title:
Deploy ATtiny13
Command:
C:\ArduBoot\avrdude.exe
Arguments:
-C C:\ArduBoot\avrdude.conf -c ftbb -P ft0 -B 9600 -p attiny13 -U flash:w:$(TargetDir)$(TargetName).hex:i
Чтобы видеть лог процесса прошивки - нужно поставить галочку рядом с пунктом "Use Output window".
Вот и всё.
Теперь, чтобы прошить МК нужно зайти в меню Tools и выбрать наш пункт "Deploy ATtiny13".
Ссылки
Делаем ISP-программатор из Arduino
Arduino/CraftDuino и WinAVR - программируем на чистом С
Про фьюзы
ATtiny13 datasheet
Atmel Studio
AVR Fuse Calculator
AVR-GCC :: СОВМЕСТИМОСТЬ КОДА
Прошивка и программирование ATtiny13 при помощи Arduino
Core13
How to integrate AVRDude with Atmel Studio
ADC and PWM basics on the ATtiny13 (github)
По теме
Как запустить код Arduino на ATtiny
Arduino как фреймворк
Что за язык программирования используется для Arduino?
КМБ для начинающих ардуинщиков
Ардуино что это и зачем?
Почему Arduino побеждает и почему он здесь, чтобы остаться?
Arduino, термины, начало работы
0 комментариев на «“Переходим от Arduino к программированию ATtiny13 на C”»
есть еще хорошая статья по теме
phpjs.ru/2017/12/03/arduino-прошивка-attiny13/