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