Der Compiler erkennt keinen Fehler und der Code wird kompiliert und ausgeführt. Um zu sehen, was passiert, müssen wir die Magie hinter den Kulissen erforschen. Für eine Zusammenfassung springen Sie zum Ende.
Die zweite Zeile in Ihrem Code ist, wo die Magie passieren wird und wo wir uns konzentrieren müssen.
pinMode(pin, OUTPUT);
Der pinMode
für diese Diskussion relevante Teil ist:
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
}
(Die vollständige Implementierung finden Sie in wiring_digital.c )
Hier digitalPinToBitMask
scheint also pin
ein Zwischenbit zu berechnen. Weiter erforschen, digitalPinToBitMask
ist ein Makro definiert, in Arduino.h
dessen Definition dieser Einzeiler ist:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Dieser seltsam aussehende Einzeiler erledigt eine sehr einfache Aufgabe. Es indiziert das P- te Element im Array digital_pin_to_bit_mask_PGM
und gibt es zurück. Dieses Array digital_pin_to_bit_mask_PGM
ist in pins_arduino.h
oder in der Pin-Map für die jeweilige verwendete Karte definiert .
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),
...
};
Dieses Array enthält insgesamt 20 Elemente, daher haben wir kein Glück. 999 indiziert einen Speicherort im Flash-Speicher außerhalb dieses Arrays, was zu einem unvorhersehbaren Verhalten führt. Oder wird es?
Wir haben noch eine andere Verteidigungslinie gegen die Laufzeitanarchie. Es ist die nächste Zeile der Funktion pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
führt uns auf einem ähnlichen Weg. Es wird zusammen mit als Makro definiert digitalPinToBitMask
. Seine Definition lautet:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Nun indizieren wir das P- te Element, digital_pin_to_port_PGM
dessen Array in der Pin-Map definiert ist:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Dieses Array enthält 20 Elemente, sodass 999 wieder außerhalb des Bereichs liegt. Wiederum liest dieser Befehl einen Wert aus dem Flash-Speicher und gibt ihn zurück, dessen Wert wir nicht sicher sein können. Dies wird von nun an wieder zu unvorhersehbarem Verhalten führen.
Es gibt noch eine letzte Verteidigungslinie. Das ist das if
Einchecken pinMode
des Rückgabewerts von digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
ist definiert als 0 in Arduino.h
. Wenn also das zurückgegebene Byte von digitalPinToPort
zufällig Null ist, pinMode
schlägt dies stillschweigend fehl und kehrt zurück.
pinMode
Kann uns auf keinen Fall vor Anarchie retten. 999 ist dazu bestimmt, zum Untergang zu führen.
TL; DR, der Code wird ausgeführt und das Ergebnis ist unvorhersehbar. Höchstwahrscheinlich wird kein Pin auf gesetzt und OUTPUT
fällt digitalWrite
aus. Wenn Sie außergewöhnlich viel Pech haben, wird möglicherweise ein zufälliger Pin auf gesetzt OUTPUT
und auf digitalWrite
gesetzt HIGH
.