Kompiler tidak akan mendeteksi kesalahan dan kode akan dikompilasi dan dijalankan. Karena itu, untuk melihat apa yang terjadi, kita perlu menjelajahi keajaiban di belakang layar. Untuk ringkasan, lewati hingga selesai.
Baris kedua dalam kode Anda adalah di mana keajaiban akan terjadi dan di situlah kita perlu fokus.
pinMode(pin, OUTPUT);
Bagian yang pinMode
relevan dengan diskusi ini adalah:
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
}
(Implementasi lengkap dapat ditemukan di wiring_digital.c )
Jadi, di sini, digitalPinToBitMask
tampaknya digunakan pin
untuk menghitung bit menengah. Menjelajahi lebih lanjut, digitalPinToBitMask
adalah makro yang didefinisikan dalam Arduino.h
definisi yang satu garis ini:
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
Kapal yang terlihat aneh ini melakukan tugas yang sangat sederhana. Ini indeks P th elemen dalam array digital_pin_to_bit_mask_PGM
dan kembali itu. Array digital_pin_to_bit_mask_PGM
ini didefinisikan dalam pins_arduino.h
atau pin map untuk papan khusus yang digunakan.
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),
...
};
Array ini memiliki 20 elemen total, jadi kami kurang beruntung. 999 akan mengindeks lokasi memori dalam memori flash di luar array ini, sehingga mengarah ke perilaku yang tidak terduga. Atau akankah itu?
Kami masih memiliki garis pertahanan lain terhadap anarki runtime. Ini baris fungsi berikutnya pinMode
:
uint8_t port = digitalPinToPort(pin);
digitalPinToPort
membawa kita di jalan yang sama. Ini didefinisikan sebagai makro bersama dengan digitalPinToBitMask
. Definisinya adalah:
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
Sekarang, kita indeks P th unsur digital_pin_to_port_PGM
yang merupakan array didefinisikan dalam peta pin:
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
....
PC,
PC,
};
Array ini mengandung 20 elemen, jadi 999 lagi di luar jangkauan. Sekali lagi, perintah ini membaca dan mengembalikan nilai dari memori flash yang nilainya tidak dapat kita yakini. Ini lagi akan mengarah pada perilaku yang tidak terduga mulai dari sini.
Masih ada satu garis pertahanan terakhir. Itu adalah if
check-in pinMode
atas nilai pengembalian dari digitalPinToPort
:
if (port == NOT_A_PIN) return;
NOT_A_PIN
didefinisikan sebagai 0 in Arduino.h
. Jadi, jika byte yang dikembalikan dari digitalPinToPort
kebetulan menjadi nol, maka pinMode
diam-diam akan gagal dan kembali.
Bagaimanapun, pinMode
tidak dapat menyelamatkan kita dari anarki. 999 ditakdirkan untuk menghasilkan malapetaka.
TL; DR, kode akan dieksekusi dan hasilnya tidak dapat diprediksi. Kemungkinan besar, tidak ada pin yang akan disetel OUTPUT
, dan digitalWrite
akan gagal. Jika Anda mengalami nasib buruk, maka pin acak mungkin diatur ke OUTPUT
, dan digitalWrite
dapat mengaturnya HIGH
.
uint8_t
sehingga pertama akan dikonversi ke 231 oleh pemanggilan kodepinMode
. Hasil akhirnya sama:pinMode
dandigitalWrite
akan memiliki perilaku yang tidak dapat diprediksi dan dapat mengalahkan bagian memori acak jika Anda memanggilnya dengan argumen pin yang buruk.Di perpustakaan standar, ada makro yang dirancang untuk mengubah pin ke port, yang digunakan dalam perakitan. Inilah mereka untuk Uno dari Arduino 1.0.5:
Ada lebih banyak, tetapi saya tidak akan menunjukkannya di sini.
Saya yakin program Anda akan mengurangi 14 dari 999, yang masih terlalu besar untuk program ini. Kemudian akan mencoba untuk menunjuk ke elemen 985 dari
digital_pn_to_bit_mask_PGM
array, yang hanya berisi 20 elemen. Ini kemungkinan besar akan berakhir mengacaukan Arduino dengan menunjuk ke titik acak dalam progmem.sumber