6

マイクロコントローラー用の組み込み C コードを書いています。コードは 3 つの異なる回路基板間で共有する必要があり、入力/出力構成は、初期化中にいくつかのテーブルから実行時に設定されます。

マイクロコントローラーには 24 の ADC チャネルがあり、ピンを ADC チャネルとして設定またはクリアできる機能があります。これは、関数への入力が 0 から 23 (テーブルに設定されている) のみで構成されることを意味します。

関数が0-23以外の値を受け取ったことを識別し、何らかのエラーまたは警告をスローし、誰かが無効な値を入れた場合にコードがコンパイルされないようにする、ある種のプリプロセッサまたはコンパイラの「もの」を配置したいと思いますテーブル。

これを行う最善の方法について誰かアドバイスがありますか?

4

2 に答える 2

3

#errorほとんどのコンパイラ(プリプロセッサ)では、ディレクティブを使用できます。

つまり

#define ADC_CHANNEL 34
#if ADC_CHANNEL > 23
#error ADC_CHANNEL exceeds maximum allowed value
#endif

上記はエラーをスローし、コンパイルされません。

次に、ADC_CHANNELを関数への入力として使用します。

または、を作成ADC_CHANNELして、、...enumを定義することもできます。次に、関数に型、または呼び出したいものを指定します。そうすると、列挙型を引数として関数が呼び出された場合、範囲外の値を使用する方法がなくなります。ADC_CHANNEL_0 = 0ADC_CHANNEL_1 = 1ADC_CHANNEL_23 = 23ADC_CHANNEL_t

例:

typedef enum {ADC_CHANNEL_0 = 0,
              ADC_CHANNEL_1 = 1,
              ADC_CHANNEL_2 = 2,
              // ...etc...
              ADC_CHANNEL_22 = 22,
              ADC_CHANNEL_23 = 23} adc_channel_t;

void setClearAdcPin(adc_channel_t adcChannel) {
    // ...function body...
}

= 0(コンパイラは順序からそれを推測するため、技術的には、、などは必要ありません= 1。デフォルトでは、enumsは0から始まり、値ごとに1ずつ増加します。ただし、各値を手動で定義する方が安全であり、さまざまなことができます。連続していなくても、使用する可能性のある3つの可能なADCチャネルのみを含めるようにします。)

于 2012-11-05T18:17:41.570 に答える
1

この汚いトリックによって、(プリプロセッサではなく) コンパイラで範囲を確認できます。

const char PIN = 23;
struct check_23 {
    unsigned long bits: PIN+9;
};

PIN > 23 の場合、これはコンパイルされません

次に、関数の引数としてコンパイル時の定数のみが与えられるようにするには、関数の代わりにマクロを指定します。

#define CONCAT(a, b) a##b
#define MAKESTRUCTNAME(a,b) CONCAT(a,b)

#define PinFunction(PinArg)\
struct MAKESTRUCTNAME(PinCheckStruct, __LINE__) {\
    unsigned long bits: (PinArg)+9;\
};\
RealPinFunction(PinArg);\
于 2012-11-05T18:30:53.557 に答える