Trình biên dịch sẽ không phát hiện bất kỳ lỗi nào và mã sẽ biên dịch và thực thi. Do đó, để xem những gì xảy ra chúng ta cần khám phá phép thuật đằng sau hậu trường. Để tóm tắt, bỏ qua để kết thúc.
Dòng thứ hai trong mã của bạn là nơi phép màu sẽ xảy ra và đó là nơi chúng ta cần tập trung.
pinMode(pin, OUTPUT);
Phần pinMode
có liên quan đến cuộc thảo luận này là:
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
}
(Việc thực hiện đầy đủ có thể được tìm thấy trong Wired_digital.c )
Vì vậy, ở đây, digitalPinToBitMask
dường như đang sử dụng pin
để tính toán một bit trung gian. Khám phá thêm, digitalPinToBitMask
là một macro được định nghĩa trong Arduino.h
đó định nghĩa của nó là một lớp lót:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Điều này trông lạ lùng một lót làm một nhiệm vụ rất đơn giản. Nó lập chỉ mục phần tử thứ P trong mảng digital_pin_to_bit_mask_PGM
và trả về nó. Mảng digital_pin_to_bit_mask_PGM
này được xác định trong pins_arduino.h
hoặc sơ đồ pin cho bảng cụ thể đang được sử dụng.
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),
...
};
Mảng này có tổng cộng 20 yếu tố, vì vậy chúng tôi không gặp may. 999 sẽ lập chỉ mục một vị trí bộ nhớ trong bộ nhớ flash bên ngoài mảng này, do đó dẫn đến hành vi không thể đoán trước. Hay nó sẽ?
Chúng tôi vẫn có một tuyến phòng thủ chống lại tình trạng hỗn loạn thời gian chạy. Đây là dòng tiếp theo của chức năng pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
đưa chúng ta theo một con đường tương tự. Nó được định nghĩa là một macro cùng với digitalPinToBitMask
. Định nghĩa của nó là:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Bây giờ, chúng tôi lập chỉ mục phần tử thứ P digital_pin_to_port_PGM
là một mảng được xác định trong sơ đồ pin:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Mảng này chứa 20 phần tử, vì vậy 999 lại nằm ngoài phạm vi. Một lần nữa, lệnh này đọc và trả về một giá trị từ bộ nhớ flash có giá trị mà chúng ta không thể chắc chắn. Điều này một lần nữa sẽ dẫn đến hành vi không thể đoán trước từ đây.
Vẫn còn một tuyến phòng thủ cuối cùng. Đó là if
kiểm tra pinMode
giá trị trả về của digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
được định nghĩa là 0 in Arduino.h
. Vì vậy, nếu byte trả về từ digitalPinToPort
xảy ra bằng 0, thì pinMode
sẽ âm thầm thất bại và trả về.
Trong mọi trường hợp, pinMode
không thể cứu chúng tôi khỏi tình trạng hỗn loạn. 999 được định sẵn để dẫn đến kết cục.
TL; DR, mã sẽ thực thi và kết quả của việc này sẽ không thể đoán trước. Nhiều khả năng, sẽ không có pin nào được đặt thành OUTPUT
và digitalWrite
sẽ thất bại. Nếu bạn vô cùng xui xẻo, thì một chốt ngẫu nhiên có thể được đặt thành OUTPUT
và digitalWrite
có thể được đặt thành HIGH
.