我在Arduino设备上使用C语言,其中的引脚标记不同。我使用的是PLAIN C,而不是Arduino的“语言”。
每个引脚由其端口(例如PORTB
)和端口中的引脚(位)定义(例如PB0
)。
我想简洁别名别名,所以我可以制作宏或函数,就像Arduino使用的那样:
pin_direction(D2, 1); // D2 as output
set_pin(D2, 0); // write zero to D2
pin_direction(D3, 0); // D3 as input
enable_pullup(D3, 1); // enable D3 pullup
相反(atm)我必须使用像这样丑陋的东西:
#define D0 0
#define D1 1
#define D2 2
#define D3 3
...
#define D10 2
#define D11 3
#define PORT_D0 PORTD
#define PORT_D1 PORTD
#define PORT_D2 PORTD
#define PORT_D3 PORTD
...
#define PORT_D10 PORTB
#define PORT_D11 PORTB
// the same for PIN_xx and DDR_xx
然后我可以使用宏来完成工作:
#define sbi(port, bit) (port) |= _BV(bit)
#define cbi(port, bit) (port) &= ~ _BV(bit)
sbi(DDR_D2, D2); // D2 to output
cbi(PORT_D2, D2); // D2 to output
sbi(DDR_D3, D3); // D3 as input
sbi(PORT_D3, D3); // D3 pullup enable
现在这样可行,但它非常混乱。任何想法 - 如果没有巨大的switch
之类的怪物开销 - 做得更好 - 更像我的第一个例子?以某种方式枚举所有位,然后动态解析正确的寄存器?
我正在使用avr-libc avr-gcc。
答案 0 :(得分:3)
您可以定义扩展为多个令牌的宏,例如
#define PIN_D0 PORTD, 0
#define PIN_D1 PORTD, 1
...
#define PIN_D10 PORTB, 2
然后在宏中使用它们,例如:
sbi(PIN_D0); // expands to sbi(PORTD, 0)
可能对这些宏有用的一些实用程序宏是:
#define PORT_OF(port, bit) port
#define BIT_OF(port, bit) bit
可以在以下语境中使用:
PORT_OF(PIN_D10) // expands to PORTB
BIT_OF(PIN_D10) // expands to 2
答案 1 :(得分:1)
这是我使用的解决方案。
在我的util.h中(我所有的AVR项目都很常见):
#define DDR_REG(port) DDR ## port
#define PORT_REG(port) PORT ## port
#define PIN_REG(port) PIN ## port
#define SET_BIT(port, bit) do { (port) |= (1 << (bit)); } while(0)
#define CLR_BIT(port, bit) do { (port) &= ~(1 << (bit)); } while(0)
#define BIT_IS_SET(port, bit) ((((uint8_t)(port)) >> ((uint8_t)(bit))) & 0x1)
#define IO_SET_INPUT_AUX(port, bit) CLR_BIT(DDR_REG(port), bit)
#define IO_SET_AS_INPUT(io) IO_SET_INPUT_AUX(io)
#define IO_SET_OUTPUT_AUX(port, bit) SET_BIT(DDR_REG(port), bit)
#define IO_SET_AS_OUTPUT(io) IO_SET_OUTPUT_AUX(io)
#define IO_OUTPUT_0_AUX(port, bit) CLR_BIT(PORT_REG(port), bit)
#define IO_OUTPUT_0(io) IO_OUTPUT_0_AUX(io)
#define IO_OUTPUT_1_AUX(port, bit) SET_BIT(PORT_REG(port), bit)
#define IO_OUTPUT_1(io) IO_OUTPUT_1_AUX(io)
#define IO_GET_INPUT_AUX(port, bit) BIT_IS_SET(PIN_REG(port), bit)
#define IO_GET_INPUT(io) IO_GET_INPUT_AUX(io)
在我的pin映射文件中:
#define UPBTN_IO B,7
#define DOWNBTN_IO D,0
#define ENTERBTN_IO D,1
(etc)
在代码中:
IO_SET_AS_INPUT(UPBTN_IO);
这依赖于一些有趣的预处理器位,就像在宏参数上只有一轮宏扩展一样。