从CW32定时器库看联合体嵌套

乐活   2025-01-30 16:40   内蒙古  

一定要把这个库函数吃透,才能灵活掌握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)结构体,可以访问寄存器的特定位。
所以我们
  1. 用 CR1 读取整个 32 位寄存器
  2. 用 CR1_f 直接操作寄存器的具体位

就是这个样子

  1. regValue 用于整体访问寄存器
  2. regBits 用于操作寄存器的单个位
  3. 无论修改 regValue 还是 regBits,它们都指向同一块内存,所以修改一个变量,另一个变量也会同步变化。

我们使用的时候可以这样,深入进去可以改位

  1. 如果 CR1 直接赋值 0x01,它会覆盖整个寄存器的所有位。
  2. 如果 CR1_f.EN = 1,它 只会修改 EN 位,而不会影响其他位。


所以这个东西就是这样的

  1. typedef 定义新类型名,简化数据结构的使用。也就是把BTIM1给定义了一次
  2. struct 定义数据结构,组织多个变量。
  3. 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(启用定时器)。

云深之无迹
纵是相见,亦如不见,潇湘泪雨,执念何苦。
 最新文章