Le compilateur ne détectera aucune erreur et le code se compilera et s'exécutera. Par conséquent, pour voir ce qui se passe, nous devons explorer la magie des coulisses. Pour un résumé, passez à la fin.
La deuxième ligne de votre code est l'endroit où la magie se produira et c'est là que nous devons nous concentrer.
pinMode(pin, OUTPUT);
La partie pinMode
pertinente de cette discussion est:
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
}
(L'implémentation complète peut être trouvée dans le câblage_digital.c )
Donc, ici, digitalPinToBitMask
semble utiliser pin
pour calculer un bit intermédiaire. En explorant plus loin, digitalPinToBitMask
une macro définie dans Arduino.h
la définition de laquelle est cette ligne unique:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Cette doublure à l'aspect étrange fait une tâche très simple. Il indexe le P ème élément du tableau digital_pin_to_bit_mask_PGM
et le renvoie. Ce tableau digital_pin_to_bit_mask_PGM
est défini dans pins_arduino.h
ou la carte des broches de la carte spécifique utilisée.
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),
...
};
Ce tableau comprend 20 éléments au total, nous n'avons donc pas de chance. 999 indexera un emplacement de mémoire dans la mémoire flash en dehors de cette baie, conduisant ainsi à un comportement imprévisible. Ou bien?
Nous avons encore une autre ligne de défense contre l'anarchie d'exécution. C'est la prochaine ligne de la fonction pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
nous emmène sur un chemin similaire. Il est défini comme une macro avec digitalPinToBitMask
. Sa définition est:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Maintenant, nous indexons l' élément P thdigital_pin_to_port_PGM
qui est un tableau défini dans la carte des broches:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Ce tableau contient 20 éléments, donc 999 est à nouveau hors de portée. Encore une fois, cette commande lit et renvoie une valeur de la mémoire flash dont nous ne pouvons pas être certains. Cela conduira à nouveau à un comportement imprévisible à partir de maintenant.
Il reste encore une dernière ligne de défense. Il s'agit de l' if
enregistrement de pinMode
la valeur de retour de digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
est défini comme 0 po Arduino.h
. Donc, si l'octet retourné de digitalPinToPort
se trouve être nul, il pinMode
échouera et reviendra en silence.
En tout cas, pinMode
ne peut pas nous sauver de l'anarchie. Le 999 est destiné à entraîner une perte.
TL; DR, le code s'exécutera et le résultat sera imprévisible. Très probablement, aucune broche ne sera définie OUTPUT
et digitalWrite
échouera. Si vous avez une malchance exceptionnelle, une épingle aléatoire peut être définie sur OUTPUT
et digitalWrite
peut être définie sur HIGH
.
uint8_t
afin qu'il soit d'abord converti en 231 par l'appel de codepinMode
. Le résultat final est le même:pinMode
ildigitalWrite
aura un comportement imprévisible et pourrait encombrer des parties aléatoires de la mémoire si vous les appelez avec un mauvais argument pin.Dans les bibliothèques standard, il existe des macros conçues pour convertir les broches en ports, qui sont utilisées dans l'assemblage. Les voici pour l'Uno d'Arduino 1.0.5:
Il y en a plus, mais je ne les montrerai pas ici.
Je crois que votre programme soustrait 14 de 999, ce qui serait encore trop gros pour le brogramme. Il essaierait alors de pointer vers le 985e élément du
digital_pn_to_bit_mask_PGM
tableau, qui ne contient que 20 éléments. Cela finirait très probablement par visser l'Arduino en pointant vers un endroit aléatoire dans le programme.la source