Mar*_*lin 2 c macros header-files libraries
我正在为微控制器编写一些库,为此,我使用类似宏的函数.例如,启用I2C模块的类似宏的函数定义为:
#define I2C_MODULE_ENABLE(_x) \
I2C##_x##CONLbits.I2CEN = 1
Run Code Online (Sandbox Code Playgroud)
_x模块编号在哪里(例如,1或2在我的情况下).
如果用户将此宏调用函数称为I2C_MODULE_ENABLE(1),则它将由预处理器扩展为I2C1CONLbits. I2CEN = 1.
但是,如果用户将这个类似宏的函数称为I2C_MODULE_ENABLE(MY_I2C),其中MY_I2C是config.h我的i2c.h库包含的用户定义文件中定义的宏常量(例如,宏常量定义为#define MY_I2C 1),则类宏函数将被扩展作为I2CMY_I2CCONLbits. I2CEN = 1.
我知道我需要MY_I2C在连接之前以某种方式评估宏常量,我可以通过添加另一个宏级别来做到这一点:
#define __I2CxCONLbits(_x) I2C##_x##CONLbits
#define I2C_MODULE_ENABLE(_x) \
__I2CxCONLbits.I2CEN = 1
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否有一个更优雅的解决方案,因为我有多个寄存器,如CONLbits寄存器.使用这种方法,我需要__I2CxREGISTER(_x)为每个寄存器定义一个特殊的宏.
我试着这样做:
#define __I2Cx(_x) I2C##_x
#define I2C_MODULE_ENABLE(_x) \
__I2Cx(_x)##CONLbits.I2CEN = 1
Run Code Online (Sandbox Code Playgroud)
但是产生这样的输出:I2C1 CONLbits .I2CEN = 1,我的编译器抱怨它们之间的空格I2C1和CONLbits令牌.
正如我所看到的,您没有正确添加宏级别.通常的习惯用法是定义一个除了转发参数之外什么都不做的包装器.这样,如果参数本身是一个宏,它将被传播,然后传递给包装的宏:
#define I2C_MODULE_ENABLE__(x_) \
I2C##x_##CONLbits.I2CEN = 1
#define I2C_MODULE_ENABLE(x_) \
I2C_MODULE_ENABLE__(x_)
Run Code Online (Sandbox Code Playgroud)
我冒昧地重命名你的宏参数,因为带有前导下划线的标识符被定义为为实现保留,我认为安全比抱歉更好.
为了解决你的空间问题,我将使用众所周知的间接级别,并使用像宏这样的函数来生成正确的前缀令牌,并将其传递到两个级别以确保它正确扩展:
#define I2Cx__(x_) I2C##x_
#define I2C_MODULE_ENABLE__(IC_) \
IC_##CONLbits.I2CEN = 1
#define I2C_MODULE_ENABLE_(IC_) \
I2C_MODULE_ENABLE__(IC_)
#define I2C_MODULE_ENABLE(x_) \
I2C_MODULE_ENABLE_(I2Cx__(x_))
Run Code Online (Sandbox Code Playgroud)
在这里看到它
整个过程是为了确保预处理器在每一步都能看到并生成有效的令牌.这可能有点令人厌倦.
| 归档时间: |
|
| 查看次数: |
249 次 |
| 最近记录: |