คอมไพเลอร์จะไม่ตรวจพบข้อผิดพลาดใด ๆ และรหัสจะรวบรวมและดำเนินการ ดังนั้นเพื่อดูว่าเกิดอะไรขึ้นเราต้องสำรวจเวทย์มนตร์เบื้องหลัง สำหรับการสรุปข้ามไปสิ้นสุด
บรรทัดที่สองในรหัสของคุณคือสิ่งที่เวทมนตร์จะเกิดขึ้นและนั่นคือสิ่งที่เราต้องมุ่งเน้น
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) ) )
สายการบินเดียวที่ดูประหลาดนี้ใช้งานง่ายมาก มันดัชนีพีTHองค์ประกอบในอาร์เรย์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 THองค์ประกอบของ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และอาจจะตั้งค่าให้digitalWriteHIGH