Компилятор не обнаружит никаких ошибок, а код скомпилируется и выполнится. Следовательно, чтобы увидеть, что происходит, нам нужно исследовать закулисную магию. Для краткого изложения, пропустите до конца.
Вторая строка в вашем коде - это то, где произойдет волшебство, и именно на этом мы должны сосредоточиться.
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
. Таким образом, если возвращенный байт from digitalPinToPort
окажется равным нулю, pinMode
произойдет молчание и произойдет возврат.
В любом случае, pinMode
не может спасти нас от анархии. 999 суждено привести к гибели.
TL; DR, код будет выполнен, и результат этого будет непредсказуемым. Скорее всего, ни один из выводов не будет установлен на OUTPUT
и digitalWrite
выйдет из строя. Если вам случается исключительно неудача, то случайный пин-код может быть установлен на OUTPUT
и digitalWrite
может быть установлен на HIGH
.
uint8_t
поэтому сначала он будет преобразован в 231 с помощью вызова кодаpinMode
. Конечный результат то же:pinMode
иdigitalWrite
будет иметь непредсказуемые и может затирать случайные части памяти , если вы их называете с плохим контактным аргументом.В стандартных библиотеках есть макросы, предназначенные для преобразования выводов в порты, которые используются в сборке. Вот они для Uno от Arduino 1.0.5:
Есть еще, но я не буду показывать их здесь.
Я полагаю, что ваша программа вычтет 14 из 999, что все равно будет слишком большим для программы. Затем он попытается указать на 985-й элемент
digital_pn_to_bit_mask_PGM
массива, который содержит только 20 элементов. Скорее всего, это приведет к закручиванию Arduino, указывая на случайное место в программе.источник