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

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

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

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

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

您可以只定义指向寄存器的指针,然后使用常规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 (ie set bits 16 and 17) *my_register = val; // write register 

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

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

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

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

 +-- bit 31 +-- bit 0 | | vv 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; 

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

 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;