如何更改32位寄存器特定位而不更改其他位?

时间:2012-11-02 13:40:01

标签: c bit-manipulation

我想直接使用其物理地址来操作寄存器的某些位。但是我找不到办法来做到这一点。我看到一些关于设置位掩码的帖子,但我发现它们太混乱了。

我的寄存器物理地址是:0x4A10005C

我想操纵它在18-16位之间的位。我想在这些位中设置0x3

如果你们能提供答案或方法,我将非常高兴。感谢。

3 个答案:

答案 0 :(得分:7)

您可以定义一个指向寄存器的指针,然后使用普通的C按位操作来操作各个位:

volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;
                              // set up a pointer to the register

uint32_t val = *my_register;  // read register

val &= ~(0x7 << 16);          // clear bits 16..18

val |= (0x3 << 16);           // set bits 16..18 to 0x03 (i.e. set bits 16 and 17)

*my_register = val;           // write register

(以上假设您正在讨论寄存器中的三位,位16,17和18,并且您希望将位18设置为零,将位16和17设置为1.)

答案 1 :(得分:5)

位掩码很容易理解,所以让我们首先完成:

假设您的32位寄存器现在包含一些值我会随意选择0xF48C6219 16

我假设您知道如何将十六进制转换为二进制,如果不是...让我们只说使用计算器或谷歌(而不是进入那个细节)。所以我们的十六进制值可以用二进制表示为:

+-- bit 31                            +-- bit 0
|                                     |
v                                     v 
1111 0100 1000 1100 0110 0010 0001 1001
                ^ ^                       
                | |
                +-+-- bits you want to set, 16-18

布尔逻辑告诉我们:
1)OR'd(|)与1的任何内容都会为您提供1的值。或“设置”该位。
2)与&的任何AND'd(0)为您提供0的值。或者“清除”这一点。

因此,如果我们想要清除16-18位,你可以用以下掩码对它进行AND操作:

基数:1111 0100 1000 1100 0110 0010 0001 1001 2 == 0xF48C6219 16
面膜编号:1111 1111 1111 1000 1111 1111 1111 1111 2 == 0xFFF8FFF 16

   1111 0100 1000 1100 0110 0010 0001 1001
&  1111 1111 1111 1000 1111 1111 1111 1111
------------------------------------------
   1111 0100 1000 1000 0110 0010 0001 1001

现在你可以将它与你想要设置的任何东西进行对比:

新掩码编号:0000 0000 0000 0011 0000 0000 0000 0000 2 == 0x00030000 16

  1111 0100 1000 1000 0110 0010 0001 1001
| 0000 0000 0000 0011 0000 0000 0000 0000
-----------------------------------------
  1111 0100 1000 1011 0110 0010 0001 1001

所以在代码中:

#define CLEAR_MASK 0x70000 //70000 is shorter to write, so just do this and flip it
#define SET_3_MASK 0x30000

volatile uint32_t * const reg = (uint32_t *) 0x4A10005C;//set a pointer to the register
*reg &= ~CLEAR_MASK; //~ filps the bits
*reg |= SET_3_MASK;

你可以通过移位等来制作技巧,但这是位掩码的基础知识及其工作原理。希望它有所帮助。

答案 2 :(得分:0)

structure r32 {
unsigned int bit0  :1;
unsigned int bit1  :1;
unsigned int bit2  :1;
unsigned int bit3  :1;
unsigned int bit4  :1;
unsigned int bit5  :1;
.
.
.
unsigned int bit31 :1;
}

在主

structure r32 *p;
volatile uint32_t * const my_register = (uint32_t *) 0x4A10005C;

p = (structure r32 *) my_register;

然后访问第5位,例如

p->bit4 = 0;