【问题标题】:Is there a way to define macro for pins in AVR gcc so i can access those as variables?有没有办法为 AVR gcc 中的引脚定义宏,以便我可以将它们作为变量访问?
【发布时间】:2019-07-25 23:25:48
【问题描述】:

我正在尝试为 AVR C 代码编写定义,以便我可以通过简单的宏来访问引脚

STATUS_LED_OUT =1; 

在 GENET_HW_DEF.h 文件中,包含在主 C 文件中。您可以通过将此文件包含到任何 C 项目中来重现此错误。 我正在使用 avr studio 6.2 和 7 - 两者都给出相同的结果。我无法编译得到奇怪的宏展开消息,如下所示。 (CPU ATMega1284p)

D:\_SVN\Compass\AVR\Compass_IO_proto\Compass IO_proto\GENET_HW_DEF.h(19,49): error: expected ')' before '&' token
         #define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt
                                                         ^
D:\_SVN\Compass\AVR\Compass_IO_proto\Compass IO_proto\GENET_HW_DEF.h(42,25): info: in expansion of macro 'REGISTER_BIT'
          #define STATUS_LED_OUT REGISTER_BIT(PORTB,7)
                                 ^
D:\_SVN\Compass\AVR\Compass_IO_proto\Compass IO_proto\GENET_HW_DEF.h(46,2): info: in expansion of macro 'STATUS_LED_OUT'
          STATUS_LED_OUT=1;
          ^

很有趣,复制到只有一两个声明的新项目可以正常编译,直到对声明进行任何更改 - 比如添加另一个宏引用。然后又卡住了。

另外 - 如果我评论所有宏的用法,比如

STATUS_LED_DIR=1;
STATUS_LED_OUT=1; 

然后我可以编译项目,然后在取消注释使用行之后它仍然可以正常编译.. 直到执行 clean。我可能在搞乱宏观怪癖,但我不知道在哪里。

typedef struct
{
    unsigned int bit0:1;
    unsigned int bit1:1;
    unsigned int bit2:1;
    unsigned int bit3:1;
    unsigned int bit4:1;
    unsigned int bit5:1;
    unsigned int bit6:1;
    unsigned int bit7:1;
} _io_reg;

#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt

#ifndef GENET_HW_DEF
#define GENET_HW_DEF

// define functionalities and flags - comment/uncomment apropriate lines
#define GENET_USART_0 256
#define GENET_USART_1 256
#define F_CPU 20000000UL
#define STATUS_LED 7
#define ERROR_LED 4
#define ADC_GLOBAL_ENABLE A
#define ADC_CHANNEL_0 0
#define ADC_CHANNEL_1 4
#define ADC_CHANNEL_2 2
#define ADC_CHANNEL_3 3
#define ADC_CHANNEL_4 1
#define ADC_CHANNEL_5 5
#define ADC_CHANNEL_6 6
#define ADC_CHANNEL_7 7

// actual definitions and initialization
#ifdef STATUS_LED
    #define STATUS_LED_OUT REGISTER_BIT(PORTB,STATUS_LED)
    #define STATUS_LED_DIR REGISTER_BIT(DDRB,STATUS_LED)
    #define STATUS_LED_PIN REGISTER_BIT(PINB,STATUS_LED)
    STATUS_LED_DIR=1;
    STATUS_LED_OUT=1;
#endif

#ifdef ERROR_LED
    #define ERROR_LED_OUT REGISTER_BIT(PORTC,ERROR_LED)
    #define ERROR_LED_DIR REGISTER_BIT(DDRC,ERROR_LED)
    ERROR_LED_DIR=1;
    ERROR_LED_OUT=1;
#endif

#ifdef GENET_USART_0
    #define USART0_ENABLED
    #define UART_RX0_BUFFER_SIZE GENET_USART_0
    #define UART_TX0_BUFFER_SIZE GENET_USART_0
#endif

#ifdef GENET_USART_1
    #define USART1_ENABLED
    #define UART_RX1_BUFFER_SIZE GENET_USART_1
    #define UART_TX1_BUFFER_SIZE GENET_USART_1
#endif

#endif

【问题讨论】:

  • 但是,当你可以创建一个内联函数,你为什么还要使用宏呢?
  • 您的一般方法似乎是可行的,前提是您可以确保结构和目标 I/O 端口之间的所需映射(这绝对是一个重要的问题)。如果您需要帮助诊断错误消息,那么我们需要在上下文中查看它们——最好是可以重现它们的最小上下文,即minimal reproducible example
  • 因为一个新项目没有问题,并且因为它在你在你的 IDE 中执行“清理”之前编译,所以我会说这不是 AVR gcc 或其预处理器的问题。也许 IDE 有一些魔力会阻碍你。
  • 我更新了内容,所以可以重现错误。仍然不知道从这里去哪里。

标签: c gcc macros avr


【解决方案1】:

我重现了您的问题。 您不能在代码执行流程之外调用STATUS_LED_DIR=1;。这必须在函数内部(例如main())。 现在你会以其他编译错误结束,但这是主要错误。

第二次更正,concatenation需要2级

#define CONCAT(bt)  bit##bt 
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->CONCAT(bt)

【讨论】:

  • 额外级联的原因是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
相关资源
最近更新 更多