gd32 的官方库中提供了一些基础的宏定义,这些宏定义在官方库中随从可见,所有我们有必要弄清楚这些宏定义的功能和使用方法。

这里我们来学习和了解下 gd32f1x0.h 给我们提供的“位运算”宏定义。

1
2
3
4
5
6
7
/* bit operations */
#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr))
#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr))
#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr))
#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x)))
#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end))))
#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start))

REG32(addr)

该宏定义用来读写32位地址的值, (*(volatile uint32_t *)(uint32_t)(addr)) 首先将 addr 转换为 uint32_t,然后再将 uint32_t 转换为 (volatile uint32_t )指针,最后的 ‘“代表解引用,解引用后就可以读写了。

REG16(addr) 和 REG8(addr)

功能和 REG32(addr) 类似。

BIT(X)

该宏定义的功能是生成一个 uint32_t 类型的值,该值中第 X 位为 1

BITS(start, end)

通过一个具体的例子来了解 BITS 的具体实现。

1
BITS(0, 3)

调用该宏会生成一个怎样的数字,把03带入到宏定义中如下:

1
#define BITS(start=0, end=3)             ((0xFFFFFFFFUL << (start=0)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end=3))))

首先 (0xFFFFFFFFUL << (start=0)) 的结果是 0xFFFFFFFFUL 不变;其次要计算(0xFFFFFFFFUL >> (31U - (uint32_t)(end=3))) 的结果,结果为 (0xFFFFFFFFUL >> 28) 等于15,也就是二级制的 1111。从这个例子中可以看到该宏的作用就是生成一个32位的无符号从 startend 之间为 1 二进制的值。start0 开始。

GET_BITS(regval, start, end)

从定义可以看出,该宏定义的作用就是把一个指定位范围转换后的值放到 regval 中。