更改寄存器中的多个位

时间:2016-04-09 13:40:31

标签: c embedded bit-manipulation bitwise-operators

我有一个8位寄存器,我想改变第4,5和6位而不改变其他位。 这些位可以取值000111的值(无论它们之前的状态如何)。 是否有一种方法可以一步更改它们,还是必须单独更改它们?

4 个答案:

答案 0 :(得分:1)

您可以通过按位运算来完成,即首先清除3位,然后设置它们:

unsigned char value = 0x70;
unsigned char r = 0xFF;
r = (r & 0x8F) | value;

答案 1 :(得分:1)

你需要一个掩码将所请求的位置于已知状态,根据我的编程习惯,0更方便,然后使用或操作设置你想要的位1并写入回:

#define mask 0x70    // 01110000b bit 4, 5 & 6 set
reg = (reg & ~mask) | (newVal & mask);

我们使用反转掩码将要更改的位设置为0,将未更改的掩码设置为0,将我们不想干扰的位设置为0。
如果您确定新值的不需要的位始终为0,则可以简化:

#define mask 0x8f    // 10001111b bit 4, 5 & 6 reset
reg = (reg & mask) | newVal;    //newVal must have always bits 7, 3, 2, 1 & 0 reset.

答案 2 :(得分:1)

您可以在结构中使用bit-field

typedef struct{
    unsigned char b0_3 : 4;
    unsigned char b4_6 : 3;
    unsigned char b7   : 1;
}your_reg_type;

your_reg_type my_register;

//modify only the bits you need
my_register.b4_6 = 0x02;

在尝试和order your bit-field accordingly

之前,查看编译器如何命令结构中的位

答案 3 :(得分:0)

许多解决方案和变体都是可能的(并且已经有过建议),但是如果三个连续位的值本身具有意义(即它是0到7的值而不是简单的独立标志的集合)或者控制位(例如),将值保持为简单的数值范围0到7而不是直接编码值中位位置的细节可能是有用的。在这种情况下:

     assert( val <= 7 ) ;  // During debug (when NDEBUG not defined) the
                           // assert trap will catch out-of-range inputs

     reg = (reg & mask) | (val << 4) ;

当然,以这种方式简化界面需要付出一些小成本(通过添加移位操作),但优点是对寄存器字段布局细节的了解仅限于一个地方。