この質問は上記のものと似ていますが、これは別の状況です。
int pin = 999;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
この場合はどうなりますか?コンパイラはそれをキャッチするかもしれませんが、乱数を使用した場合、IDEはそれをキャッチしますか?
この質問は上記のものと似ていますが、これは別の状況です。
int pin = 999;
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
この場合はどうなりますか?コンパイラはそれをキャッチするかもしれませんが、乱数を使用した場合、IDEはそれをキャッチしますか?
回答:
コンパイラはエラーを検出せず、コードはコンパイルおよび実行されます。したがって、何が起こるかを確認するには、舞台裏の魔法を探る必要があります。概要については、最後までスキップしてください。
コードの2行目は、魔法が発生する場所であり、そこに焦点を当てる必要があります。
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
次の1行で定義されているマクロです。
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
この奇妙に見える1つのライナーは非常に単純なタスクを実行します。配列のP 番目の要素にインデックスを付けて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 番目の要素にインデックスを付け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
ます。
uint8_t
ので、最初にコード呼び出しによって231に変換されることを忘れていますpinMode
。最終的な結果は同じですpinMode
し、digitalWrite
予期しない動作を持つことになりますし、あなたが悪いのピン引数でそれらを呼び出す場合は、メモリのランダムな部分を壊しことができます。
標準ライブラリには、ピンをポートに変換するために設計されたマクロがあり、アセンブリで使用されます。ここにArduino 1.0.5のUno用があります:
#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)))
他にもありますが、ここでは表示しません。
あなたのプログラムは999から14を引くと思いますが、それでもbrogramには大きすぎます。次に、digital_pn_to_bit_mask_PGM
配列の985番目の要素(20個の要素しか含まない)をポイントしようとします。これはおそらく、progmem内のランダムなスポットを指すことによってArduinoをねじ込むことになります。