如何仅将寄存器的一部分更改为数字(示例做错了吗?)
How to change only part of a register to a number (Examples are doing it wrong?)
我想将数字 32 写入寄存器的 16-24 位。该寄存器长 100 位,其余或部分寄存器包含不应写入的 "reserved bits"(根据数据表。)或者可以说它包含我不想更改的其他值(上一个设置。).
如果只有几位,我可以为每个位设置 R &= ~(1 << x)
或 R |= 1 << x
。但是如果是一个数字, 把 32 转成二进制,一个一个地做,那就太痛苦了。我看到一些例子基本上做了类似 R = 0x20 << 16
的事情。但我很困惑。这不会破坏所有其他位并将保留位设置为 0 来扰乱 MCU 操作吗?
这里有一个函数来理解原理:
unsigned SetSomeBits(unsigned Var, unsigned StartBitNumber, unsigned NumberOfBits, unsigned Value2Set)
{
unsigned Mask = (1<<NumberOfBits)-1; //With NumberOfBits=3 Mask becomes 0b000111
Mask <<= StartBitNumber;
//Mask contains now 0 at do-not-touch bit positions
//Mask contains now 1 at to-be-changed bit positions
Var &= ~Mask; //Zero out the to-be-changed bits
return Var | (Value2Set<<StartBitNumber); //Set the requested bits
}
...此处作为宏:
#define SET_SOME_BITS(Var, StartBitNumber, NumberOfBits, Value2Set) ((Var) & ~(((1<<(NumberOfBits))-1)<<(StartBitNumber)) | (Value2Set)<<(StartBitNumber))
如果 Value2Set 不适合 NumberOfBits,两个版本都会失败。
I want to write for example the number 32 to the 16-24 bits of a register. This register is 100 bits long and the rest or some of the register contains "reserved bits" that shouldn't be write to (According to the datasheet.) or lets say it contains other values I don't want to change(Previous settings.).
您想执行 Read-Modify-Write。在这种情况下,您有兴趣将位 16-24 设置为特定值。假设这些值为零,您可以这样做:
my_register |= (32 << 16);
这是一个 Bitwise-OR 操作,需要注意这一点很重要,因为它会保留位的任何值。
假设这些值为 non-zero,您需要先清除这些位,然后写入新值。你可以这样做:
my_register &= ~(0xFF << 16); //Clear bits 16-24
my_register |= (0x20 << 16); //Set bits 16-24 to 32
上面使用了按位与、按位或、按位取反。同样,这些操作保持其他位的值。
I see some of the examples basically do something like R = 0x20 << 16.
but I'm confused. wouldn't that ruin every other bit and set the
reserved bits to 0 messing with the MCU Operation?
这不一定是真的。这些位可能是写保护的,或者这些位的默认值可能是 0,因此向它们写入 0 无效。就看MCU本身了。
我想将数字 32 写入寄存器的 16-24 位。该寄存器长 100 位,其余或部分寄存器包含不应写入的 "reserved bits"(根据数据表。)或者可以说它包含我不想更改的其他值(上一个设置。).
如果只有几位,我可以为每个位设置 R &= ~(1 << x)
或 R |= 1 << x
。但是如果是一个数字, 把 32 转成二进制,一个一个地做,那就太痛苦了。我看到一些例子基本上做了类似 R = 0x20 << 16
的事情。但我很困惑。这不会破坏所有其他位并将保留位设置为 0 来扰乱 MCU 操作吗?
这里有一个函数来理解原理:
unsigned SetSomeBits(unsigned Var, unsigned StartBitNumber, unsigned NumberOfBits, unsigned Value2Set)
{
unsigned Mask = (1<<NumberOfBits)-1; //With NumberOfBits=3 Mask becomes 0b000111
Mask <<= StartBitNumber;
//Mask contains now 0 at do-not-touch bit positions
//Mask contains now 1 at to-be-changed bit positions
Var &= ~Mask; //Zero out the to-be-changed bits
return Var | (Value2Set<<StartBitNumber); //Set the requested bits
}
...此处作为宏:
#define SET_SOME_BITS(Var, StartBitNumber, NumberOfBits, Value2Set) ((Var) & ~(((1<<(NumberOfBits))-1)<<(StartBitNumber)) | (Value2Set)<<(StartBitNumber))
如果 Value2Set 不适合 NumberOfBits,两个版本都会失败。
I want to write for example the number 32 to the 16-24 bits of a register. This register is 100 bits long and the rest or some of the register contains "reserved bits" that shouldn't be write to (According to the datasheet.) or lets say it contains other values I don't want to change(Previous settings.).
您想执行 Read-Modify-Write。在这种情况下,您有兴趣将位 16-24 设置为特定值。假设这些值为零,您可以这样做:
my_register |= (32 << 16);
这是一个 Bitwise-OR 操作,需要注意这一点很重要,因为它会保留位的任何值。
假设这些值为 non-zero,您需要先清除这些位,然后写入新值。你可以这样做:
my_register &= ~(0xFF << 16); //Clear bits 16-24
my_register |= (0x20 << 16); //Set bits 16-24 to 32
上面使用了按位与、按位或、按位取反。同样,这些操作保持其他位的值。
I see some of the examples basically do something like R = 0x20 << 16. but I'm confused. wouldn't that ruin every other bit and set the reserved bits to 0 messing with the MCU Operation?
这不一定是真的。这些位可能是写保护的,或者这些位的默认值可能是 0,因此向它们写入 0 无效。就看MCU本身了。