C AVR清洁引脚别名解决方案-枚举I/O位

C AVR清洁引脚别名解决方案-枚举I/O位,c,avr,avr-gcc,C,Avr,Avr Gcc,我在一个Arduino设备上用C语言工作,在那里管脚的标签不同。我使用的是纯C语言,而不是Arduino“语言” 每个管脚由其端口(如PORTB)和端口(如PB0)中的管脚(位)定义 我想简明扼要地使用别名pins,这样我就可以使宏或函数有点像Arduino所使用的: pin_direction(D2, 1); // D2 as output set_pin(D2, 0); // write zero to D2 pin_direction(D3, 0); // D3 as input enab

我在一个Arduino设备上用C语言工作,在那里管脚的标签不同。我使用的是纯C语言,而不是Arduino“语言”

每个管脚由其端口(如
PORTB
)和端口(如
PB0
)中的管脚(位)定义

我想简明扼要地使用别名pins,这样我就可以使宏或函数有点像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
取而代之的是(自动取款机),我必须使用这样丑陋的东西:

#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
现在可以了,但是很乱。你知道如何在没有巨大的
开关之类的巨大开销的情况下,更好地做到这一点吗?更像我的第一个例子?以某种方式枚举所有位,然后动态解析正确的寄存器


我将avr gcc与avr libc一起使用。

您可以定义扩展到多个令牌的宏,例如

#define PIN_D0    PORTD, 0
#define PIN_D1    PORTD, 1
...
#define PIN_D10   PORTB, 2
然后在宏中使用它们,例如:

sbi(PIN_D0);  // expands to sbi(PORTD, 0)
PORT_OF(PIN_D10)  // expands to PORTB
BIT_OF(PIN_D10)   // expands to 2
对于这些宏可能有用的一些实用程序宏包括:

#define PORT_OF(port, bit) port
#define BIT_OF(port, bit)  bit
可在以下上下文中使用:

sbi(PIN_D0);  // expands to sbi(PORTD, 0)
PORT_OF(PIN_D10)  // expands to PORTB
BIT_OF(PIN_D10)   // expands to 2

您可以定义扩展为多个标记的宏,例如

#define PIN_D0    PORTD, 0
#define PIN_D1    PORTD, 1
...
#define PIN_D10   PORTB, 2
然后在宏中使用它们,例如:

sbi(PIN_D0);  // expands to sbi(PORTD, 0)
PORT_OF(PIN_D10)  // expands to PORTB
BIT_OF(PIN_D10)   // expands to 2
对于这些宏可能有用的一些实用程序宏包括:

#define PORT_OF(port, bit) port
#define BIT_OF(port, bit)  bit
可在以下上下文中使用:

sbi(PIN_D0);  // expands to sbi(PORTD, 0)
PORT_OF(PIN_D10)  // expands to PORTB
BIT_OF(PIN_D10)   // expands to 2

这是我使用的解决方案

在my util.h(我的所有AVR项目通用)中:

代码:

IO_SET_AS_INPUT(UPBTN_IO);

这依赖于一些有趣的预处理器位,比如在宏参数上只有一轮宏扩展。

以下是我使用的解决方案

在my util.h(我的所有AVR项目通用)中:

代码:

IO_SET_AS_INPUT(UPBTN_IO);

这依赖于一些有趣的预处理器位,比如在宏参数上只进行了一轮宏扩展。

这部分解决了问题,但也许这是最干净的方法。对于每个I/O引脚(DDR、端口、引脚),我仍然需要三个不同的宏。嗯,您认为您仍然需要多个宏吗?给我一个例子,看看那些看起来像什么不同的一个DDR,端口和引脚位与一个IO引脚。但我想这很好。这部分解决了问题,但也许这是最干净的方法。对于每个I/O引脚(DDR、端口、引脚),我仍然需要三个不同的宏。嗯,您认为您仍然需要多个宏吗?给我一个例子,看看那些看起来像什么不同的一个DDR,端口和引脚位与一个IO引脚。但我想这很好。这很好,我会自定义它并添加到我的库中。谢谢。如果您有兴趣,请查看一下(和calc.h文件)。和你一起工作真是太好了@可能做得很好。你的位测试/设置比我的更惯用。我想我会把你的实现偷回来。:-)这太棒了,我将对它进行一些自定义并添加到我的库中。谢谢。如果您有兴趣,请查看一下(和calc.h文件)。和你一起工作真是太好了@可能做得很好。你的位测试/设置比我的更惯用。我想我会把你的实现偷回来。:-)