O compilador não detectará nenhum erro e o código será compilado e executado. Portanto, para ver o que acontece, precisamos explorar a mágica dos bastidores. Para um resumo, pule para o final.
A segunda linha do seu código é onde a mágica acontecerá e é aí que precisamos nos concentrar.
pinMode(pin, OUTPUT);
A parte pinMode
relevante para esta discussão é:
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
}
(A implementação completa pode ser encontrada em fiação_digital.c )
Então, aqui, digitalPinToBitMask
parece estar usando pin
para calcular um bit intermediário. Explorando ainda mais, digitalPinToBitMask
é uma macro definida em Arduino.h
cuja definição é esta linha única:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Este forro de aparência estranha faz uma tarefa muito simples. Ele indexa o elemento P th na matriz digital_pin_to_bit_mask_PGM
e o retorna. Essa matriz digital_pin_to_bit_mask_PGM
é definida no pins_arduino.h
mapa de pinos da placa específica que está sendo usada.
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),
...
};
Essa matriz possui 20 elementos no total, então estamos sem sorte. 999 indexará um local de memória na memória flash fora dessa matriz, levando a um comportamento imprevisível. Ou será?
Ainda temos outra linha de defesa contra a anarquia de tempo de execução. É a próxima linha da função pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
nos leva por um caminho semelhante. É definido como uma macro junto com digitalPinToBitMask
. Sua definição é:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Agora, indexamos o elemento P th , digital_pin_to_port_PGM
que é uma matriz definida no mapa de pinos:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Essa matriz contém 20 elementos, portanto, 999 está novamente fora de alcance. Novamente, este comando lê e retorna um valor da memória flash cujo valor não podemos ter certeza. Isso levará novamente a um comportamento imprevisível a partir de agora.
Ainda existe uma última linha de defesa. Esse é o if
check-in pinMode
no valor de retorno de digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
é definido como 0 pol Arduino.h
. Portanto, se o byte retornado de digitalPinToPort
for zero, pinMode
falhará e retornará silenciosamente.
De qualquer forma, pinMode
não pode nos salvar da anarquia. 999 está destinado a resultar em desgraça.
TL; DR, o código será executado e o resultado será imprevisível. Provavelmente, nenhum pino será definido OUTPUT
e digitalWrite
falhará. Se você tiver uma sorte excepcionalmente ruim, um pino aleatório pode ser definido como OUTPUT
e digitalWrite
pode ser definido como HIGH
.
uint8_t
pelo que seria primeiro convertido em 231 pela chamada de códigopinMode
. O resultado final é o mesmo:pinMode
edigitalWrite
terá um comportamento imprevisível e poderá estragar partes aleatórias da memória se você as chamar com um argumento incorreto.Nas bibliotecas padrão, existem macros projetadas para converter pinos em portas, que são usadas na montagem. Aqui estão eles para o Uno do Arduino 1.0.5:
Há mais, mas não vou mostrá-las aqui.
Acredito que seu programa subtraia 14 de 999, o que ainda seria muito grande para o submarino. Ele tentaria apontar para o 985º elemento da
digital_pn_to_bit_mask_PGM
matriz, que contém apenas 20 elementos. Provavelmente, isso acabaria atrapalhando o Arduino, apontando para um ponto aleatório no programa.fonte