一定要把这个库函数吃透,才能灵活掌握ARM单片机!
从CW32L010看HAL库封装方式 我之前写过一个,但是今天看的时候发现还有我不懂的,再总结一下。
从最近看的BTIM开起~

嘿

然后映射
BTIM_TypeDef 结构体对应于 MCU 基本定时器(Base Timer,BTIM) 的 寄存器映射,起始地址为 0x40004800,总大小为 48 字节(0x30)。

注意这里是现

这是一段

对比数据手册是倒着封装的

就是功能位
结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。联合体的所有成员在内存中具有相同的首地址,共占同一段内存空间,这些成员可以相互覆盖,因此联合体也常常被称作共用体,在不同的时间保存不同的数据类型和不同长度的成员的值。也就是说,在某一时刻,只有最新存储的成员是有效的。运用此种类型数据的优点是节省存储空间。
这个库的设计是结构体里面有个共用体,共用体里面有结构体。
CR1_f
这里的 CR1_f 结构体用于 位域(Bit-Field) 方式操作寄存器的特定位。C 语言的位域(bit-field)是一种特殊的结构体成员,允许我们按位对成员进行定义,指定其占用的位数。
这三个是空

14,13,12,三位
寄存器通常是 32 位的,但每个位有不同的作用,如果使用普通结构体变量,需要用位运算(|, &)来设置特定位,非常麻烦。位域(Bit-Field)允许我们直接操作特定位,而不需要手动位运算,大幅提高可读性。
继续看这个联合体里面有结构体
联合体(union)的所有成员共享相同的内存地址,它的大小等于最大成员的大小。
这个是完整的
在这个 union 里:CR1 是一个 完整的 32 位寄存器,可以一次性访问整个寄存器的值。
这个是位域结构体
CR1_f 是 位域(Bit-Field)结构体,可以访问寄存器的特定位。

就是这个样子
- 无论修改 regValue 还是 regBits,它们都指向同一块内存,所以修改一个变量,另一个变量也会同步变化。

我们使用的时候可以这样,深入进去可以改位
- 如果 CR1 直接赋值 0x01,它会覆盖整个寄存器的所有位。
- 如果 CR1_f.EN = 1,它 只会修改 EN 位,而不会影响其他位。

所以这个东西就是这样的
- typedef 定义新类型名,简化数据结构的使用。也就是把BTIM1给定义了一次
- union 使不同访问方式共享同一块内存,提高寄存器操作的灵活性。

对比一下

名字叫BTIM

首先定义一个TIM的初始化结构体

这个就是里面要操作的东西

然后就可以通过结构体的方法来把要设置的值写进去

然后我们对定时器初始化,传一个外设的结构体和对应的设置结构体。

一开始函数里面判断这个参数对不对

后面这个IS开头的就是这个功能

参数ok的话,开始更改。
后面的是我们的设置结构体,给到了前面外设结构体的位域里面。

里面还有修改寄存器的位
#define REGBITS_MODIFY(REG, MASK, VALUE) ((REG) = ((REG) & ~(MASK)) | (VALUE))

先清除再写入
先是寄存器,然后是要修改的位置,然后是新值。

我们再看一个使能定时器的
NewState ? A : B 是 C 语言的三元运算符(三目运算符)

就是这样的

展开后的样子

再看看这个
BTIMx->CR1 是 BTIM 控制寄存器 1,其 EN 位(Bit 0)用于控制定时器的启动与停止。
这就是第一个寄存器组
BTIMx_CR1_EN_Msk 是一个掩码(mask),表示 EN 位
在这里
|= 按位或(OR)运算:将 CR1 的 Bit 0 位置 1(启用定时器)。