GD32库中常用的位操作REGIDX_BIT(regidx, bitpos)

在GD32的库里面,经常看到

#define RCU_REGIDX_BIT(regidx, bitpos)   (((uint32_t)(regidx)<<6) | (uint32_t)(bitpos))

#define RCU_REG_VAL(periph)  (REG32(RCU + ((uint32_t)(periph)>>6)))  

#define RCU_BIT_POS(val)   ((uint32_t)(val) & 0x1FU) 

这样的写法

GD32将寄存器地址偏移REGDIX 和 里面控制位BIT偏移组合成1个新的32bit数值! 

所以这个比较绕。 它的操作,都是基于这个新的32bit值的。 比如向右>>6,就可以获得寄存器的地址偏移。  (REG32(RCU + ((uint32_t)(periph)>>6)))   则就得到了完整的寄存器地址。而((uint32_t)(val) & 0x1FU) 则可以得到位的偏移,然后通过BIT()这个偏移量,即可将具体的位置1.

还是很巧妙的。 里面运用的次数较多,所以这里单独来分析了。

下面是库文件中的具体例子:

将RCU的寄存器地址偏移REGDIX 和 里面控制位BIT偏移组合成1个新的32bit数值! 

#define RCU_REGIDX_BIT(regidx, bitpos)      (((uint32_t)(regidx)<<6) | (uint32_t)(bitpos))


RCU_REGIDX_BIT将寄存器偏移REGDIX和控制位BIT组合成一个32位的值,以后就可以用了
具体,方法就是,把REGDIX左移动了<<6位,然后把控制位偏移量bitpos拼到结尾上去的。


#define RCU_REG_VAL(periph)  (REG32(RCU + ((uint32_t)(periph)>>6)))  


把这个RCU_REGIDX_BIT向右>>6bit,去掉了位偏移,也就还原了REGIDX_BIT ,就得到了外设偏移 ,这样再加上RCU的基地址,这样就可以读出该寄存器的值了
 

#define RCU_BIT_POS(val)   ((uint32_t)(val) & 0x1FU) 


RCU_BIT_POS() 这个功能就是将上面组合好的32位值填到里面,它可以算出具体控制位的偏移。
0x1FU 表示限制后5位,为啥是5位?  0b000....1 1111
由于某个寄存器中,位的偏移最多就是[0~31], 所以用5bit就可以表示这个偏移位数了。 

比如这里的IDX_AHBRST,它的偏移是十进制的17U,二进制为0b000....1 0001
这样在做RCU_BIT_POS()之后与0x1FU进行与运算,那就得到了17这个值然后执行BIT(17),则把第17位置1了。 也就是设置了该位的值。


这个是宏定义,IDX_AHBRST  = 0x28U, 
这个是另一个别名定义 periph


typedef enum
{
    RCU_GPIOARST   = RCU_REGIDX_BIT(IDX_AHBRST, 17U),        
    RCU_GPIOBRST   = RCU_REGIDX_BIT(IDX_AHBRST, 18U),           
    RCU_GPIOCRST   = RCU_REGIDX_BIT(IDX_AHBRST, 19U),          
    RCU_GPIOFRST   = RCU_REGIDX_BIT(IDX_AHBRST, 22U),     
}rcu_periph_reset_enum;

 

你可能感兴趣的:(碎片知识,GD32,gd32,嵌入式,单片机)