1

我正在用 C 语言为嵌入式处理器编写固件。我想将所有配置信息放在一个名为 config.h 的头文件中。这会导致 ADC 初始化出现问题,简单的 #defines 无法解决问题。现在代码是这样的:

配置文件

#define NUMBER_OF_POTS  1
#define POT_1_CHANNEL  27

ADC.c

#define MAKE_CSS(channel) _CSS##channel
#define CALL_MAKE_CSS(channel) MAKE_CSS(channel)

void initialize_adc() {
   CALL_MAKE_CSS(POT_1_CHANNEL);
}

如果我将 config.h 更改为:

#define NUMBER_OF_POTS  2
#define POT_1_CHANNEL  27
#define POT_2_CHANNEL  29

adc.c 应该只是自动添加一个CALL_MAKE_CSS带有一些宏技巧的秒。

我想问题是:是否有一个技巧可以为您提供带有宏的 for 循环功能?

谢谢,

史蒂夫。

4

5 回答 5

3

我没有测试这个:

// config.h

#define NUMBER_OF_POTS  2
extern int pots[];

// config.c

int pots[NUMBER_OF_POTS] = {
    27,
    29
};


// adc.c

void initialize_adc() {
    for (int i = 0; i < NUMBER_OF_POTS; i++) {
        CALL_MAKE_CSS(pots[i]);
    }
}
于 2009-02-28T15:10:27.027 回答
1

您不必完全依赖宏。只需将您的“幻数”定义为#defines。

例如:

在 config.h 中:

#define NUMBER_OF_POTS 2
#define POT_1_CHANNEL  27
#define POT_2_CHANNEL  29

unsigned int PotChannelList[NUMBER_OF_POTS] = {POT_1_CHANNEL, POT_2_CHANNEL};

在 adc.c 中:

for(i = 0; i < NUMBER_OF_CHANNELS; i++)
{
  initialize_adc(PotChannelList[i]);
}

您仍然在 config.h 中定义设置,并且在添加通道时不必更改 adc.c。您只需将其添加到列表中。列表顺序还定义了初始化的顺序。

编辑:很抱歉格式混乱......

于 2009-02-28T15:07:25.083 回答
0

看看boost.preprocessor。尽管 boost 通常用于 C++,但预处理器元编程库可以很好地使用 CPP,因此它可以满足您的需求。它提供了一些数据结构(列表、元组)和迭代宏。

抱歉,如果它真的能做到你想要的,或者至少提供另一种方式,我无法给你任何例子,因为我很少需要它,而且它太早了。

注意刚刚看到施罗德的回答。如果没有必要不依赖PP仍然是最好的选择......

于 2009-02-28T15:08:23.940 回答
0

C 预处理器不能执行循环。您要么必须在 C 代码中执行循环,要么如果您真的需要在编译时执行类似循环的操作,您可以编写自己的预处理器(可以只是一个简单的 shell 脚本,例如),生成必要的代码。

于 2009-03-02T01:05:58.973 回答
0

虽然你不能用预处理器做循环,但你可以做展开的循环。所以如果你知道你永远不会拥有超过 4 个底池,你可以这样做;

void initialize_adc() {
  #if NUMBER_OF_POTS > 0
    CALL_MAKE_CSS(POT_1_CHANNEL);
  #endif
  #if NUMBER_OF_POTS > 1
    CALL_MAKE_CSS(POT_2_CHANNEL);
  #endif
  #if NUMBER_OF_POTS > 2
    CALL_MAKE_CSS(POT_3_CHANNEL);
  #endif
  #if NUMBER_OF_POTS > 3
    CALL_MAKE_CSS(POT_4_CHANNEL);
  #endif
}

The only benefit of this compared to other solutions here is that there is no runtime overhead at all. Extra inline code "magically" appears if and only if another channel is added, just as the questioner wanted. To extract the ugliness from within the function call (at the cost of putting it earlier in your code instead), define 4 new macros each using the same #if NUMBER_OF_POTS > x technique. Then you'd be able to go simply;

void initialize_adc() {
  INIT_CSS_1();
  INIT_CSS_2();
  INIT_CSS_3();
  INIT_CSS_4();
}
于 2009-03-02T02:41:55.467 回答