Компілятор не виявить жодної помилки, і код буде компілювати та виконувати. Отже, щоб побачити, що трапиться, нам потрібно вивчити магію поза кадром. Для резюме, пропустіть до кінця.
Другий рядок у вашому коді - це те, де буде відбуватися магія, і саме там нам потрібно зосередитися.
pinMode(pin, OUTPUT);
Частина, що pinMode
стосується цієї дискусії, становить:
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin); //The first instance where pin is used
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return;
//Do something
}
(Повну реалізацію можна знайти в wiring_digital.c )
Отже, тут, digitalPinToBitMask
здається, використовується pin
для обчислення проміжного біта. Далі вивчаючи, digitalPinToBitMask
- це макрос, визначений у Arduino.h
визначенні цього однорівневого:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Цей дивно виглядає один лайнер виконує дуже просте завдання. Він індексує P- й елемент у масиві digital_pin_to_bit_mask_PGM
та повертає його. Цей масив digital_pin_to_bit_mask_PGM
визначений у pins_arduino.h
або контактній карті для конкретної плати, яка використовується.
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(0), /* 0, port D */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
...
};
У цьому масиві всього 20 елементів, тож нам не пощастило. 999 індексує місце пам'яті у флеш-пам’яті поза цим масивом, що призводить до непередбачуваної поведінки. Або буде?
У нас ще є інша лінія захисту від анархії виконання. Наступний рядок функції pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
веде нас схожим шляхом. Він визначається як макрос разом із digitalPinToBitMask
. Його визначення:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Тепер ми індексуємо P- й елемент, digital_pin_to_port_PGM
який є масивом, визначеним на контактній карті:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Цей масив містить 20 елементів, тому 999 знову виходить за межі діапазону. Знову ж таки, ця команда зчитує та повертає значення з флеш-пам'яті, значення якої ми не можемо бути впевнені. Це знову призведе до непередбачуваної поведінки з цього моменту.
Є ще одна остання лінія захисту. Це if
реєстрація pinMode
на повернене значення digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
визначається як 0 в Arduino.h
. Отже, якщо повернутий байт з digitalPinToPort
нуля буде нульовим, то pinMode
він мовчки вийде з ладу і повернеться.
У будь-якому випадку pinMode
не може врятувати нас від анархії. 999 призначено призвести до приреченості.
TL; DR, код буде виконуватися, і результат цього буде непередбачуваним. Швидше за все, жоден штифт не буде встановлено OUTPUT
, і digitalWrite
він не вийде. Якщо у вас є надзвичайно невдача, то випадковий штифт може встановитись OUTPUT
і digitalWrite
може встановити його HIGH
.