操作寄存器的时候,经常需要获取或设置寄存器某些bit的值,为了方便,可以定义如下的宏
方法1:
#define GETBITFIELD(ulRegVal, ulOffset, ulBitWidth) \
(((ulRegVal)>>(ulOffset)) & ((1UL << (ulBitWidth)) - 1))
#define SETBITFIELD(ulRegVal, ulOffset, ulBitWidth, ulChangeVal) \
((ulRegVal) & (~(((1UL << (ulBitWidth))-1) << ulOffset)) \
| (((ulChangeVal)&((1UL << (ulBitWidth)) - 1))<<(ulOffset)))
方法2:
#define GETPOS(ulField) ((unsigned short)(ulField)>>8)
#define GETWIDTH(ulField) ((unsigned short)(ulField) & 0xff)
#define GETBITFIELD(ulRegVal, ulField) \
( ((ulRegVal) >> GETPOS(ulField)) & (0xffffffff >> 32-GETWIDTH(ulField)) )
#define SETBITFIELD(ulRegVal, ulField, ulChangeVal) \
(((ulRegVal) & ~((0xffffffff >> 32-GETWIDTH(ulField)) << GETPOS(ulField))) \
| ( ((ulChangeVal) & (0xffffffff >> 32-GETWIDTH(ulField))) << GETPOS(ulField) ))
/************************************************************************/
/* 使用方式;要自己保证传入的正确性 */
/************************************************************************/
unsigned int n = 0xffff;
printf("\r\n0x%x", GETBITFIELD(n, ((1<<8) | 3)));
n = SETBITFIELD(n, ((4<<8) | 1), 0);
n = SETBITFIELD(n, ((5<<8) | 2), 2);
printf("\r\n0x%x", n);
使用宏而不是函数的原因是函数有额外的开销;
扩展一下,使之可以操作64bit数
#define GETBITFIELD64(RegVal, ulField) \
( ((RegVal) >> GETPOS(ulField)) & ((unsigned __int64)(-1) >> 64-GETWIDTH(ulField)) )
#define SETBITFIELD64(RegVal, ulField, ChangeVal) \
(((RegVal) & ~(((unsigned __int64)(-1) >> 64-GETWIDTH(ulField)) << GETPOS(ulField))) \
| ( ((ChangeVal) & ((unsigned __int64)(-1) >> 64-GETWIDTH(ulField))) << GETPOS(ulField) ))