0

我正在尝试使用宏轻松更改我的头文件。我正在调试我的代码,似乎这些 MACROS 没有做它们应该做的事情。有人可以告诉我如何达到以下效果吗?LED_ID_AMS 等

#define LED_NUMBER                  (2)
#define LED_ID_X                    (0)
#define LED_ID_Y                    (1)
#define LED_PIN_X                   (0)
#define LED_PIN_Y                   (3)
#define LED_PORT_X                  (PORTE)
#define LED_PORT_Y                  (PORTG)
#define LED_DD_X                    (DDRE)
#define LED_DD_Y                    (DDRG)
#define LED_PORT(LED_ID_X)          (LED_PORT_X)
#define LED_PORT(LED_ID_Y)          (LED_PORT_Y)
#define LED_PIN(LED_ID_X)           (LED_PIN_X)
#define LED_PIN(LED_ID_Y)           (LED_PIN_Y)
#define LED_DD(LED_ID_X)            (LED_DD_X)
#define LED_DD(LED_ID_Y)            (LED_DD_Y)

我想达到什么目的?

我正在努力做到这一点,这样我就可以像这样循环端口初始化:

for(i=0;i<LED_NUMBER;i++){
    /* set data direction to output*/
    LED_DD(i)|=((0x01)<<LED_PIN(i));
    /* turn on led */
    LED_PORT(i)|=((0x01)<<LED_PIN(i));
}
4

3 回答 3

1

以后你会后悔使用太多宏。实际上,您已经后悔了,因为它们不起作用,而且作为宏,它们很难调试。

只是几点:

  • 你的LED_PIN(i)表达总是扩大到0
  • 你的LED_PORT(i)表达总是扩大到PORTE任何可能

例如LED_PIN(LED_ID_X)展开为LED_PIN_X. LED_ID_X注意,根本没有使用宏参数。相反,LED_PIN_X只是扩展为0.

于 2014-03-16T17:23:53.360 回答
0

您必须至少添加以下一项:

  • 数组
  • 内联函数
  • 更复杂的宏

在我看来,还需要取消引用硬件地址。

例如,使用宏,您可以定义:

#define LED_PORT(i) *(uint16_t *)( \
    (i) == LED_ID_X ? LED_PORT_X : \
    (i) == LED_ID_Y ? LED_PORT_Y : \
    etc)

在哪里:

#define LED_ID_X     (0)
#define LED_ID_Y     (1)
#define LED_PORT_X   (PORTE)
#define LED_PORT_Y   (PORTG)
#define PORTE        (0x11112222U) // example only
#define PORTG        (0x33334444U) // example only

uint16_t只是一个猜测:我假设 32 位地址空间中有 16 位端口。

或者,使用数组和 C99 的指定初始化器:

const uint32_t LED_PORT[] = {
    [LED_ID_X] = LED_PORT_X,
    [LED_ID_Y] = LED_PORT_Y
};

#define LED_PORT(i) (*(uint16_t *)LED_PORT[i])

当然,如果没有 C99,您可以只使用:

const uint32_t LED_PORT[] = {LED_PORT_X, LED_PORT_Y};

假设是等LED_ID_X。_0

于 2014-03-16T20:11:03.160 回答
0

这应该对您发出警告,例如LED_PORT(SOME_ARG)有几个定义。而 in只是一个虚拟参数,与您的常量绝对LED_PORT(LED_ID_X)无关。LED_ID_XLED_ID_X

您可以通过使用常量数组来使您的代码具有同样的可读性,可能像您在此处尝试做的那样从宏中使用。

除非有大量LED_ID_<foo>,否则这充其量只是一个小的简化。不要那样做。如果有很多代码与这些代码大致相同,那么定义一个对它们中的每一个迭代一些操作的宏可能是有意义的,即:

#define FROB_LEDS \\
     action(LED_ID_X); \\
     action(LED_ID_Y); \\
     action(LED_ID_Z);

action(X)在本地定义为宏以对 LED 执行操作XFROB然后action再次取消定义。很丑,真的。

于 2014-03-16T21:55:28.553 回答