C 更改寄存器中的多个位

C 更改寄存器中的多个位,c,embedded,bit-manipulation,bitwise-operators,C,Embedded,Bit Manipulation,Bitwise Operators,我有一个8位寄存器,我想在不改变其他位的情况下改变4、5和6位。 这些位的值可以从000到111(无论其先前的状态如何)。 是否有一种方法可以一步更改它们,或者我必须单独更改它们?您可以通过按位操作进行更改,即先清除3位,然后设置它们: unsigned char value = 0x70; unsigned char r = 0xFF; r = (r & 0x8F) | value; 您需要一个掩码来将请求的位置于已知状态,根据我的编程习惯,0更方便,然后使用or操作设置要为1的位并

我有一个8位寄存器,我想在不改变其他位的情况下改变4、5和6位。 这些位的值可以从
000
111
(无论其先前的状态如何)。
是否有一种方法可以一步更改它们,或者我必须单独更改它们?

您可以通过按位操作进行更改,即先清除3位,然后设置它们:

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

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

#define mask 0x70    // 01110000b bit 4, 5 & 6 set
reg = (reg & ~mask) | (newVal & mask);
我们使用反转的掩码将要更改的位设置为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.
可以在结构内部使用:

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;

在尝试之前,请检查编译器如何对结构内部的位进行排序,并且有许多解决方案和变体是可能的(并且已经提出),但是如果三个连续位的值本身有意义的话(即,它是一个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) ;

assert(val)我想你指的是按位或
?对于已知状态,我看不出
0
1
更方便。问题只是下一步你是打开想要打开的位(使用
操作),还是关闭想要关闭的位(使用
&
操作)“JohnBollinger,我认为0更方便,因为要设置想要的位,正如你所说的,你只需要在值之间有一个<代码>或<代码>,你需要重置代码< >代码>具有倒置的输入值的登记值。你需要2个操作。不,替代方案可以和你的例子一样复杂,并且不需要IV。输入:
reg=(reg | mask)和(newVal | mask)
@JohnBollinger是的,它可以是一个替代方案。我想补充一点,这是我个人的偏好,以澄清我更喜欢它,但反过来也是可能的。你的第二个例子是不正确的-如果它们当前设置在
reg
中,它永远不会清除任何位4、5或6。我认为你应该从你的ans中删除第二部分这个答案(不一定)正确,因为在C中不能保证列出的第一位是第7位。它可以是第0位。这就是为什么我说“检查目标的结尾…”对于单个字节,这不是endianness的问题,而是编译器实现的问题。事实上,即使对于多字节,这也不是endianness的问题-endianness是关于字节顺序而不是位顺序。编译器可能会打包来自MSB或LSB的位,而不管字节顺序如何。因此,请检查编译器的文档,而不是目标endianness。请注意,这可能会在同一目标的不同编译器之间发生变化。通常会提供供应商提供的编译器特定目标处理器头文件,这些头文件正好用于片上外围寄存器。如果供应商选择为您正在使用的特定工具链提供头文件,这可能会影响可移植性o可选编译器。你说得对,这是编译器实现的问题。我编辑了答案。