STM32篇-6.HAL库使能时钟函数的解读(一)

张开发
2026/4/9 16:28:40 15 分钟阅读

分享文章

STM32篇-6.HAL库使能时钟函数的解读(一)
这里拿STM32F407的__HAL_RCC_ADC1_CLK_ENABLE();进行举例。可以看到该函数其实是一个宏定义作用是使能ADC1的时钟宏定义解释1.do { ... } while(0U)作用这是一个经典的 C 语言宏定义技巧。目的将多行代码封装成一个原子操作。无论你是在if语句中使用它还是在普通函数中调用它它都能像单行代码一样安全运行不会因为分号问题导致编译错误或逻辑错误。2.__IO uint32_t tmpreg 0x00U;__IO这是volatile的别名。它告诉编译器“这个变量可能会被硬件修改或者对它的读写操作至关重要千万不要优化掉它。”tmpreg定义一个临时变量用来暂存数据。3.SET_BIT(RCC-APB2ENR, RCC_APB2ENR_ADC1EN);核心操作这是真正开启时钟的指令。RCC-APB2ENR访问APB2 外设时钟使能寄存器。ADC1 挂载在 APB2 总线上。RCC_APB2ENR_ADC1EN这是 ADC1 的时钟使能位通常是第 8 位。SET_BIT将该位置 1。效果告诉 RCC 模块“把通往 ADC1 的时钟门打开。”4.tmpreg READ_BIT(RCC-APB2ENR, RCC_APB2ENR_ADC1EN);关键操作读回这是很多初学者看不懂的地方。为什么要刚写完又读一遍原因总线同步延迟。在 Cortex-M 内核中写操作如开启时钟是发生在 AHB 总线上的而外设如 ADC1在 APB 总线上。写操作是异步的CPU 写完寄存器后可能紧接着就执行下一条指令去配置 ADC 了。此时时钟信号可能还没有真正稳定地传输到 ADC 模块。强制读回该寄存器会强制 CPU等待直到写操作真正完成并生效。这就像是你按下了电灯开关然后必须看一眼灯亮了没确认亮了再去做别的事。场景还原CPU 发出指令 A开启 ADC 时钟写寄存器。CPU 发出指令 B配置 ADC 分辨率写 ADC 寄存器。如果没有读操作CPU 速度极快指令 B 可能在指令 A 还没真正传送到 ADC 模块硬件还没通电时就到了。结果就是配置失败ADC 没反应。有了读操作CPU 发出指令 A写 RCC。CPU 发出指令 X读 RCC即tmpreg ...。关键点为了读出 RCC 的值CPU 必须等待指令 A 彻底完成硬件时钟真的打开了总线才能返回正确的数据。等读操作完成后CPU 才敢发指令 B配置 ADC。必须等到总线返回寄存器的值才执行下一个指令。5.UNUSED(tmpreg);作用消除编译器警告。原因因为开启了编译器的“未使用变量警告”如果定义了tmpreg却不使用它编译器会报错。虽然我们在第 4 步用了它为了读回但在逻辑上我们并不需要它的值。这个宏告诉编译器“我知道我没用它别报错。”6.反斜杠\反斜杠\叫做“续行符”。它告诉编译器“这一行代码还没结束下一行是接着这一行的请把它们连起来看成一行。”为什么要这么写可读性如果不加\整个do...while结构必须挤在一行里写代码会变得极长根本没法看。编译器视角加上\后虽然我们在编辑器里分了好几行写为了好看但在编译器眼里这仍然是一行完整的代码。宏的特性宏定义通常要求是一个完整的逻辑单元。如果不换行写起来太痛苦如果直接换行不加\编译器会认为宏定义在第一行就结束了后面的代码会报错。SET_BIT的本质是异或操作。即对该寄存器的第8位置1.其他的使能时钟的函数也同理这里只是带大家一起研究宏定义内的写法

更多文章