用位段、宏分别实现寄存器的位定义
1. 一个32位寄存器描述:中断使能寄存器(IER)
寄存器位 | 名称 | 属性 | 复位值 | 描述 |
31 : 8 | RFU | —— | 0x0 | RFU(未被使用的位) |
7 | PTIME | R/W | 0x0 | 略 |
6:3 | RFU | —— | 0x0 | RFU |
2 | ELSI | R/W | 0x0 | 略 |
1 | ETBEI | R/W | 0x0 | 略 |
0 | ERBFI | R/W | 0x0 | 略 |
2. 用宏实现位定义
#define ERBFI ((uint32_t)0x00000001)
#define ETBEI ((uint32_t)0x00000002)
#define ELSI ((uint32_t)0x00000004)
#define PTIME ((uint32_t)0x00000004)
宏定义数字加上类型,这样使代码更加安全,赋值出现类型匹配错误会报错。
如果要设置某些位,只需将这些位相或以后,再与该寄存器值相或:
IER |= (ELSI | PTIME);
如果要清除某些位,只需将这些位相或以后取反,再与该寄存器值相与:
IER &= ~(ELSI | PTIME);
3. 用位段实现位定义
首先定义一个位段结构体:
struct UART_IER_BIT
{
uint32_tRFU0: 24;
uint32_tPTIME: 1;
uint32_tRFU1: 4;
uint32_tELSI: 1;
uint32_tETBEI: 1;
uint32_tERBFI: 1;
};
位段操作寄存器非常方便,可以直接进行读写。但是使用位段也会带来一些问题,注重可移植性的程序应该避免使用位段。
(1) int位段被当做有符号数还是无符号数。
(2)位段中位的存放顺序,以上定义的位段是从字的高位到低位。还有从低位到高位的实现方式。根据不同的目标机器和编译器编译方式有不同的定义。
(3)当一个位段指明了两个位段,第二个位段比较大,无法容纳于第一个位段剩余的位时,编译器有可能把第二个位段放在内存的下一个存储单元,也可能直接放在第一个位段后面,从而在两个内存位置的边界上。