繁体   English   中英

动态使用不同定义的C MACRO

[英]C MACRO that dynamically use different defines

我要编写的MACRO的目的是通过一个由值,位置和长度定义的新值来更新char。 让我给你一个例子,以更好地解释:

原始值:0b11000011要更新的值:0b11放置位置:新值的长度为4:2

基本上我想在字节(0b110 00 011)的中间放置两位(0b11),以便有一个新的字节(0b110 11 011)

我现在拥有的MACRO就像

#define UPDATE_REG(REG, MASK, POS, LEN, VAL) ((REG) = (((REG) & (MASK)) | (VAL<<(POS +1 -LEN))))

而且效果很好。 例如,在标题中,我的定义如下

#define     CP_BYP_MODE_SAD                                     0x38
#define     CP_BYP_MODE_ADR                                     0xD4
#define     CP_BYP_MODE_POS                                     4
#define     CP_BYP_MODE_LEN                                     3
#define     CP_BYP_MODE_DEF                                     0b00
#define     CP_BYP_MODE_MSK                                     0b11100111

并使用宏,我编写以下代码

uint8_t Reg = 0b11000011;
UPDATE_REG(Reg, CP_BYP_MODE_MSK, CP_BYP_MODE_POS, CP_BYP_MODE_LEN, 0b11);

此解决方案效果很好,但我想指出的是,我想通过一些技巧来减少参数(如果可能),考虑到我将为每个调用使用由name_MSK name_POS name_LEN组成的三个定义

明确一点,我的目标是拥有类似

#define UPDATE_REG(REG, NAME, VAL) ((REG) = (((REG) & (**NAME_MSK**)) | (VAL<<(**NAME_POS** +1 - **NAME_LEN**))))

例如,仅通过CP_BYP_MODE就能获得CP_BYP_MODE_POS并能够自动添加_POS后缀。

首先,确实不需要为此编写晦涩的宏,这只会使代码更难阅读。 不幸的是,人们试图将简单的按位算术隐藏在抽象层后面,只是因为他们发现按位算术很棘手。

相反,您应该做的是保持简单:

uint8_t reg = 0xC3; 
uint8_t mask = 0x18;
uint8_t new_val = 0x18;
reg &= ~mask; // clear values with mask
reg |= new_val; // write new value to the cleared position

值得注意的是,如果您知道掩码,则意味着您已经知道大小和位位置。 您可以像这样根据尺寸和位置计算蒙版:

mask = ((1 << size)-1) << pos;

size = 2,pos = 3给出:
1 << 2 = 0000 0100b = 0x04
0x04-1 = 0000 0011b = 0x03
0x03 << 3 = 0001 1000b = 0x18

也许这就是您想要的:

/* this bitfield may appear in more places: */
#define TWO_BITS_FOR_ALICE 4,2 /*starting bit, length in bits*/

#define REG1_TWO_BITS_FOR_ALICE REG1,TWO_BITS_FOR_ALICE

/* this is a global bitfield, e.g. some unique hardware register: */
#define REG1_TWO_BITS_FOR_BOB   REG1,0,2 /*destination,starting bit,length in bits */

#define MASK_OUT(start,length) ~(MASK_IN((start),(length)))
#define MASK_IN(start,length) ((-1u<<(start))+(1u<<((start)+(length))))

#define SET_GBFLD(bfld,value) _SET_BFLD(bfld,value)
#define SET_BFLD(target,bfld,value) _SET_BFLD(target,bfld,value)
#define _SET_BFLD(target,start,length,value) ((target) = ((target)&MASK_OUT((start),(length))) | (((value) & MASK_IN(0,(length)))<<(start)))

#include <stdio.h>

int main(void)
{
    unsigned REG1 = 0;
    SET_GBFLD(REG1_TWO_BITS_FOR_ALICE,7);
    SET_GBFLD(REG1_TWO_BITS_FOR_BOB,7);
    printf("%04x ",REG1);

    unsigned REG2 = 0;
    SET_BFLD(REG2,TWO_BITS_FOR_ALICE,7);
    printf("%04x ",REG2);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM