От Arduino к регистрам
Восемь уроков для тех, кто уже пишет скетчи в Arduino IDE. В каждом — одна функция Arduino: что делает ядро ArduinoCore-avr под ней, построчно по исходнику, как то же самое пишется регистрами ATmega328P и чем они отличаются в тактах и времени.
8 уроков
- Урок 1. pinMode и digitalWrite изнутриТаблицы выводов, turnOffPWM, SREG и такты против SBIУрок 1 · 30 мин
- Урок 2. digitalRead и INPUT_PULLUP изнутриdigitalRead, INPUT_PULLUP, PINx, PUD и чтение порта целикомУрок 2 · 25 мин
- Урок 3. analogWrite изнутри: таймеры и частота ШИМinit(), три таймера, карта выводов, 490,2 и 976,6 Гц, своя частотаУрок 3 · 35 мин
- Урок 4. analogRead изнутри: АЦП, делитель и опорноеADMUX, ADPS = 128, опорное, внутренние каналы, АЦП по прерываниюУрок 4 · 30 мин
- Урок 5. millis, micros и delay изнутриПрерывание Timer0, FRACT_INC, micros через TCNT0, delay и свой тикУрок 5 · 35 мин
- Урок 6. attachInterrupt изнутри: INT0, INT1 и свой ISREICRA, EIMSK, EIFR, косвенный вызов, свой ISR и PCINTУрок 6 · 30 мин
- Урок 7. Serial изнутри: буферы, UBRR0 и U2XSerial.begin, U2X0, исключение 57600, буферы и прерыванияУрок 7 · 35 мин
- Урок 8. Wire и SPI против регистров TWI и SPITWBR, буфер 32 байта, коды ошибок, SPCR и SPSR, мастер на регистрахУрок 8 · 40 мин
Как устроен трек
Трек для тех, кто уже мигал светодиодом и читал датчики в Arduino IDE и хочет понять, что стоит за digitalWrite() или millis(). Все уроки — про одну плату: Arduino Uno или Nano с ATmega328P на 16 МГц. Каждый урок разбирает одну функцию Arduino по одной схеме:
- что делает ядро — исходник ArduinoCore-avr 1.8.8 с указанием файла и строк;
- регистры — то же самое через регистры ATmega328P, с разделами даташита;
- разница — такты, время, побочные эффекты и подводные камни ядра;
- задание с ответом под спойлером;
- что дальше — следующий урок, страницы регистров атласа, калькуляторы и глоссарий.
Основы — что такое DDRx и PORTx, как работает таймер и зачем volatile — здесь не повторяются: на них ссылаемся в трек «AVR с нуля». Обзор того, что ядро делает с микроконтроллером целиком, — в статье «Arduino и AVR: что скрывает ядро Arduino».
Что понадобится
- Arduino Uno или Nano с ATmega328P и кабель USB;
- светодиод с резистором 330 Ом, кнопка, потенциометр на 10 кОм, макетная плата и провода;
- Arduino IDE — регистровый код пишется прямо в скетче, отдельный тулчейн не нужен;
- по желанию — осциллограф или логический анализатор, чтобы увидеть разницу во времени своими глазами.
Откуда числа и насколько им верить
Каждое утверждение о ядре Arduino проверено по исходникам ArduinoCore-avr версии 1.8.8: по данным GitHub API тег 1.8.8 указывает на коммит 86df345 от 21 мая 2026 года. В других версиях строки могут отличаться. Регистры, биты, формулы и предельные токи — из даташита Microchip DS40002061B, такты команд — из его раздела 37 (Instruction Set Summary), имена векторов прерываний и макросов — из avr-libc.
Примеры кода написаны для avr-gcc и вычитаны по даташиту и исходникам ядра, но редакция их не компилировала и на плате не запускала. Число тактов, которое получится у вас, зависит от версии компилятора и оптимизаций, поэтому в уроках даны оценки по таблице команд и скетч, который считает такты на самой плате. Всё, что мы посчитали сами, подписано «расчёт наш».
Готовятся к публикации
tone() и Timer2 · pulseIn и захват на Timer1 · shiftOut и аппаратный SPI · Библиотека EEPROM и регистры EEAR, EEDR, EECR · Прерывания PCINT на любом выводе · Сон и энергопотребление скетча · Сторожевой таймер в скетче
Частые вопросы
Нужно ли бросать Arduino IDE, чтобы писать регистрами?
Нет. Скетч — обычная программа на C++ для avr-gcc, и имена регистров из avr-libc (PORTB, TCCR1A, ADMUX) доступны в нём без подключения заголовков. Во всех уроках трека регистровый код живёт в обычном скетче рядом с Serial и millis(); нужно только не перенастраивать то, на чём держится ядро, — Timer0 и его прерывание.
Чем этот трек отличается от «AVR с нуля»?
«AVR с нуля» начинается с пустого main() без библиотеки Arduino. Здесь отправная точка — знакомая функция Arduino: сначала разбираем её исходник в ArduinoCore-avr, потом пишем регистровый эквивалент прямо в скетче и сравниваем. Основы — DDRx, таймеры, прерывания — не повторяем, а даём ссылки на уроки «AVR с нуля».
Подойдут ли уроки для Arduino Mega или Leonardo?
Только частично. Разбор исходника ядра верен для всех плат на AVR, но таблицы выводов, таймеры и номера прерываний в уроках даны для ATmega328P — Uno, Nano и Pro Mini на 16 МГц. У ATmega2560 на Mega 2560 другие порты и шесть таймеров вместо трёх, четыре из них 16-битные, у Leonardo — ATmega32U4 с USB вместо USART0, и номера регистров нужно сверять с их даташитами.
Смотрите также
- Arduino и AVRЧто делают init(), millis(), analogWrite(), analogRead() и загрузчик
- ATmega328PРаспиновка, фьюзы, Optiboot, периферия, питание, схема и код на C
- Пины ArduinoПин Arduino → порт ATmega, ШИМ, прерывания и регистры
- Arduino IDE 2Установка, менеджер плат, порт, библиотеки, монитор порта, HEX-файл, ошибки загрузки