代表微芯片上的针的宏

时间:2015-11-23 20:05:41

标签: c macros atmega

我正在尝试用C编写一些用于atmega微控制器的代码,并且我有一个工作宏BIT_SET用于设置一个位:

#define BIT_MASK(b)  (0x01 << (b))
#define BIT_ON(p,b)  ((p) |= BIT_MASK(b))
#define BIT_OFF(p,b) ((p) &= ~BIT_MASK(b))
#define BIT_SET(p,b,v) (v ? BIT_ON(p,b) : BIT_OFF(p,b))

现在我想定义代表I / O引脚的单行宏。类似的东西:

#define LED B,5    // an LED diode is connected to bit 5 of port B
#define BUTTON B,4 // a button is connected to bit 4 of port B

最终代码中将有更多这些宏用于不同的外围设备,这只是一个简化的例子。

问题我不知道如何定义宏PORTDDR, 这样我就可以像这样使用LED(或BUTTON)宏:

BIT_SET(DDR(LED), 1);  // which should expand to: BIT_SET(DDRB, 5, 1)
BIT_SET(PORT(LED), 0); // which should expand to: BIT_SET(PORTB, 5, 0)


这是我的动力:

DDRB线控制引脚的方向(引脚是输入还是输出),
PORTB行设置输出引脚的逻辑值 因为两条线都影响同一个引脚,所以我想在一个地方选择引脚(#define LED ...) 稍后在代码中仅对两个操作使用符号名称(LEDBUTTON)(配置方向和设置输出值)。

DDRBPORTB必须能够进一步扩展(而不仅仅是一次),因为它们是在外部标头中定义的(不在我的控制之下)。 此外,我被一个使用##连接的事实所困,这阻止了宏的进一步扩展。

1 个答案:

答案 0 :(得分:0)

最后,我决定使用内联函数而不是宏,正如一些评论所建议的那样。 这是我的结果:

// enumeration for I/O ports
typedef enum 
{
    IO_B,
    IO_C,
    IO_D
} ioPort;

// structure representing one I/O pin
typedef struct
{
    ioPort port;
    uint8_t bitIx;
} ioPin;

// converts ioPort to corresponding PORTx pointer
inline volatile uint8_t* port(ioPort iop)
{
    switch(iop)
    {
    case IO_B: return &PORTB;
    case IO_C: return &PORTC;
    case IO_D: return &PORTD;    
    default:   return NULL;
    }
}

// converts ioPort to corresponding DDRx pointer
inline volatile uint8_t* ddr(ioPort iop)
{
    switch(iop)
    {
    case IO_B: return &DDRB;
    case IO_C: return &DDRC;
    case IO_D: return &DDRD;
    default:   return NULL;
    }
}

// sets one bit of a port to given value
static inline void bitSet(volatile uint8_t* port, const uint8_t bitIx, const uint8_t value)
{
    if(port)
    {
        if(value)
            *port |= (1L << bitIx);
        else
            *port &= ~(1L << bitIx);
    }        
}

// configuring where peripheral devices are connected
const ioPin led = {IO_C, 5};
const ioPin button = {IO_C, 6};

// (later in a code)
// setting direction of the pin with an led connected
bitSet(ddr(led.port), led.bitIx, 1);

我必须承认,严格来说,这不是我原来问题的答案,因为我要求使用宏的解决方案。但我希望这对某人来说仍然有用。