Geçersiz bir PIN numarası kullandığımda ne olur?


9

İlgili: Çalışma zamanı hatası varsa ne olur?

Bu soru yukarıdaki soruya benzer, ancak bu alternatif bir durumdur:

int pin = 999;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);

Bu durumda ne olur? Derleyici onu yakalayabilir, ancak rasgele bir sayı kullanırsanız IDE yakalar mı?

Yanıtlar:


9

Derleyici herhangi bir hata algılamaz ve kod derlenir ve yürütülür. Bu nedenle, neler olduğunu görmek için sahne arkasındaki sihri keşfetmeliyiz. Özet için, sonuna atlayın.


Kodunuzdaki ikinci satır, büyünün gerçekleşeceği ve odaklanmamız gereken yer.

pinMode(pin, OUTPUT);

pinModeBu tartışmayla ilgili kısmı :

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
}

(Uygulamanın tamamı wiring_digital.c adresinde bulunabilir )

Yani, burada, bir ara bit hesaplamak digitalPinToBitMaskiçin kullanılıyor gibi görünüyor pin. Daha fazla araştırmak, tanımı bu tek katmanlı olan digitalPinToBitMaskbir makrodur Arduino.h:

#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )

Bu garip görünümlü bir astar çok basit bir görev yapar. Dizideki Pth öğesini dizine alır digital_pin_to_bit_mask_PGMve döndürür. Bu dizi digital_pin_to_bit_mask_PGM, pins_arduino.hkullanılan belirli kart için tanımlanır veya pin haritası.

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),
...
};

Bu dizi toplam 20 elemente sahip, bu yüzden şansımız kalmadı. 999, flash bellekte bu dizinin dışındaki bir bellek konumunu endeksler ve böylece öngörülemeyen davranışlara yol açar. Yoksa olacak mı?

Çalışma zamanı anarşisine karşı başka bir savunma hattımız daha var. Fonksiyonun bir sonraki satırı pinMode:

uint8_t port = digitalPinToPort(pin);

digitalPinToPortBizi benzer bir yol izliyor. İle birlikte bir makro olarak tanımlanır digitalPinToBitMask. Tanımı:

#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )

Şimdi, pim öğesinde pim haritasında tanımlanan bir dizi olan Pth öğesini indeksliyoruz digital_pin_to_port_PGM:

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
    PD, /* 0 */
    PD,
    ....
    PC,
    PC,
};

Bu dizi 20 öğe içerir, bu nedenle 999 tekrar aralık dışındadır. Yine, bu komut, değerini bilmediğimiz flash bellekten bir değer okur ve döndürür. Bu da bundan sonra öngörülemeyen davranışlara yol açacaktır.

Hala son bir savunma hattı var. Yani ifonay pinMode, dönüş değerinin digitalPinToPort:

if (port == NOT_A_PIN) return;

NOT_A_PIN, 0 inç olarak tanımlanır Arduino.h. Böylece, gelen bayt digitalPinToPortsıfır olursa pinMode, sessizce başarısız olur ve geri döner.

Her durumda, pinModebizi anarşiden kurtaramaz. 999 mahkumiyetle sonuçlanır.


TL; DR, kod yürütülecek ve bunun sonucu tahmin edilemez olacaktır. Büyük olasılıkla, hiçbir pin ayarlanmaz OUTPUTve digitalWritebaşarısız olur. Eğer son derece kötü bir şansınız varsa, rastgele bir pin ayarlanmış olabilir OUTPUTve digitalWritebunu ayarlayabilir HIGH.


Sınırları kontrol etmek ilginç. digitalWrite zaten çok yavaş ve hantaldır, derleme zamanı veya çalışma zamanı kontrolleri koymak garip olmaz.
Cybergibbons

Tüm arduino pinleri bitişik bir aralıktaysa, bağlantı noktasını değiştiremezlerdi == pin kontrolünü bir pin ile değil> BOARD_MAX_PIN kontrolü, burada kart maksimum pinini, kartı algılayan bazı ifdef'lere dayanarak bazı üstbilgi dosyasında tanımlar?
EternityForest

999'un bir şekilde temsil edilemeyeceğini unutuyorsunuz, uint8_tbu yüzden önce kod çağrısı ile 231'e dönüştürülecektir pinMode. Sonuç aynıdır: pinModeve digitalWriteöngörülemeyen bir davranışa sahip olur ve kötü bir pin argümanı ile çağırırsanız, belleğin rastgele parçalarını tıkayabilir.
David Grayson

3

Standart kütüphanelerde, pimleri montajda kullanılan portlara dönüştürmek için tasarlanmış makrolar vardır. İşte Arduino 1.0.5'ten Uno için:

#define digitalPinToPCICR(p)    (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
#define digitalPinToPCMSK(p)    (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))

Dahası var, ama onları burada göstermeyeceğim.

Programınızın 999'dan 14'ü çıkartacağına inanıyorum, ki bu hala brogram için çok büyük olurdu. Daha sonra digital_pn_to_bit_mask_PGMdizinin yalnızca 20 öğe içeren 985. öğesini işaret etmeye çalışır . Bu muhtemelen progmemde rastgele bir noktaya işaret ederek Arduino'yu vidalar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.