2012-11-02 60 views
5

我想直接使用它的物理地址操作寄存器的某些位。不过,我找不到一个方法来做到这一点。我看到一些关于设置位掩码的帖子,但我觉得它们太混乱了。如何更改32位寄存器的特定位而不更改其他位?

我的寄存器进行物理地址为:0x4A10005C

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

如果你们能提供一个答案或是一种方法,我会很高兴。谢谢。

+0

没有理解位操作如何工作和像位掩码的东西,它可能是真的很难操纵位... – codewarrior

+0

什么是混淆位掩码给你? – Mike

+0

有两种方法可以访问位级信息BITWISE运算符和按位结构c –

回答

5

你可以只定义一个指针寄存器,然后用普通的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

还应该用'&〜(掩码)'清除这些位,否则除了全部位置1值如'0x7'。它是什么18是'1'? –

+0

@Hristo:谢谢 - 我想你可能错过了我之前的编辑。 –

+0

是的,这就像数据竞争条件:) –

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; 
+1

虽然这可能在大多数情况下工作(假设这些位的顺序是正确的,但它可能不是这样),但对于有关它的评论和解释,不能保证关于在C. –

5

位掩码是很容易理解让我们通过先运行:

让我们说你的32位寄存器包含一定的价值,现在我会随便挑0xF48C6219

我假设你知道如何十六进制转换为二进制,如果没有...让我们只说用计算器或谷歌(而不是进入的是细节问题太)。因此,我们的十六进制值可以用二进制表示为:

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

布尔逻辑告诉我们:与1
1)任何东西或运算(|)给你的1值。或者“设定”这个位。
2)任何AND'd(&)与0为您提供的值为0。或者“清除”这个位。

因此,如果我们想清楚位16-18即可,它带着面具,如:

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

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 == 0x00030000

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; 

你可以通过移动位等操作技巧,但这是位掩码的基础知识,以及它们如何工作。希望能帮助到你。

+0

中的位字段的排序或位置。这对我的进一步发展会有很大的帮助。 – denizt

+0

不错的格式化Mike。 :) – Whoami

0

我在做点工作时总是提到this website

+0

仅链接答案是[不是一个好答案](https://meta.stackexchange.com/q/8231/230282) –