Добро пожаловать в мир регистров портов и Pin Change Interrupts — это джедайские техники, которые сделают ваш код быстрее в сотни раз и позволят обрабатывать события так, как не снилось обычным digitalRead().
Почему digitalWrite() — это зло?
Когда вы пишете digitalWrite(13, HIGH), Arduino IDE выполняет внутри себя огромную прослойку:
- Проверяет, существует ли пин 13.
- Ищет, к какому порту (B, C или D) он относится.
- Вычисляет маску бита.
- Отключает прерывания на всякий случай.
- Меняет бит.
- Снова включает прерывания.
Все это занимает около 5 микросекунд (при 16 МГц это ~80 тактов процессора!). А теперь представьте, что вам нужно вывести картинку на LED-матрицу или управлять 8 реле одновременно — задержки становятся критическими.
Как устроены порты на Arduino Uno (ATmega328P):
Микроконтроллер разбивает все 20 пилов на три порта:
| Порт | Бит 7 | Бит 6 | Бит 5 | Бит 4 | Бит 3 | Бит 2 | Бит 1 | Бит 0 |
|---|---|---|---|---|---|---|---|---|
| PORTB | PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 |
| Пины | — | — | 13 | 12 | 11 | 10 | 9 | 8 |
| PORTC | PC6 | PC5 | PC4 | PC3 | PC2 | PC1 | PC0 | |
| Пины | Reset | A5 | A4 | A3 | A2 | A1 | A0 | |
| PORTD | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 |
| Пины | 7 | 6 | 5 | 4 | 3 | 2 | 1 (TX) | 0 (RX) |
У каждого порта есть три регистра:
- PORTx — записываем сюда, чтобы установить HIGH (1) или LOW (0) на пинах.
- DDRx (Data Direction Register) — определяем, пин работает как вход (0) или как выход (1).
- PINx — читаем состояние пинов (входной регистр).