6

我正在为微控制器编写嵌入式 C 代码。代码必须在三个不同的电路板之间共享,并且输入/输出配置是在运行时在初始化期间从一些表中设置的。

微控制器有 24 个 ADC 通道,我有一个功能可以设置或清除一个引脚作为 ADC 通道。这意味着函数的输入可以包含 0 到 23(在表中设置),仅此而已。

我想放置某种预处理器或编译器“东西”,可以识别函数接收到 0-23 以外的值并抛出某种错误或警告,并防止代码编译以防有人输入无效值桌子。

有人对如何最好地做到这一点有一些建议吗?

4

2 回答 2

3

在大多数编译器(预处理器)上,您可以使用该#error指令。

IE

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

上面会抛出一个错误,并且不会编译。

然后使用 ADC_CHANNEL 作为函数的输入。

或者您可以制作ADC_CHANNEL一个enum, 并定义ADC_CHANNEL_0 = 0, ADC_CHANNEL_1 = 1... ADC_CHANNEL_23 = 23。然后让你的函数采用 type ADC_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 回答