STM32F103C8T6--时钟、BKP、RTC、PWR、低功耗模式

一、说明

对这几个部分一个知识梳理,主要是一些注意事项和模块之间的联系。包括之前我学习的一些疑惑,特别是时钟那块。还有低功耗部分一些细节的解答

一些图片来自江协科技的课件截图和数据手册。

二、涉及到的知识点复习

一、时钟

三种不同的时钟源可被用来驱动系统时钟 (SYSCLK)
HSI 振荡器时钟
HSE 振荡器时钟
PLL 时钟
这些设备有以下 2 种二级时钟源:
40kHz 低速内部 RC ,可以用于驱动独立看门狗和通过程序选择驱动 RTC RTC 用于从停机 /
待机模式下自动唤醒系统。
32.768kHz 低速外部晶体也可用来通过程序选择驱动 RTC(RTCCLK)
当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
上面是手册里面的描述
  • 按照我自己的理解,时钟就是分为内部时钟外部时钟(I和E),然后时钟有快慢,又被分为高速时钟低速时钟(H和L)。应该是Internal和External、High和Low。
  • 手册的描述倒是挺详细的,但是我就是看不明白,为什么主频不是72MHZ,为什么时钟都这么慢。最大不就是8MHZ吗?带着疑问,往下看。
  • 如下是那个源码的注释,就是说最后选择的是HSE时钟(8MHZ),然后去锁相环倍频得到不同的频率的意思。

  • 后面的简单讲下流程,最好还是去看一下江协科技,45集视频开头有讲这个流程。
  • 文件最开头的描述是这三个函数,我想讲的是第一个,先往下划

  • 如下这个是选择主频的注释,解开注释就可以选择不同的频率。这个往下看你就明白了。

  • 先看看SystemInit,发现默认是内部高速时钟(8MHZ),这个点需要注意一下,比较关键。

  • 往下走,进入这个函数

  • 能发现就是解开不同注释执行不同路线,我们解开的注释就是72MHZ这个函数,进去看看

  • 是一些配置参数,看不明白(可以对照数据手册看,需要时间),但是我们看注释就行,就知道干了什么,发现很眼熟。

  • 打开手册看看,猜测应该就是默认走蓝色那路线(内部高速时钟8MHZ),然后开启外部时钟成功(外部高速时钟8MHZ),就会走红色这个路线(8MHZ倍频变主频的72MHZ,具体倍频多少取决我们解开哪个注释,就会执行哪个函数,就会有不同的配置)。
  • 所以如果外部晶振起振失败,主频一下着就会变成8MHZ,而不是72MHZ。往下走,继续看,验证一下想法对不对。

  • 看这个,如果成功就会给0x01,就会走下面的if

  • 如下,对应手册就是PCLK1就是36MHZ,也就是APB1,这个div1就是一分频(不变),div2就是二分频(效率变为原来的二分之一)。这个地方给的参数是二分频,就是把72/2=36
  • 按照我自己的理解,分频就是计数,假设本来计4个数字进位1,现在变成8个数字进位1,需要更多操作,效率变低。频率自然变低。
  • 总之,这个地方就是分频,定时器那块也有相似的参数。
  • 从这里也可以为之前的一些问题解答,为什么不同的总线,有的主频最高只有36MHZ,就是在这里分频的。

  • 因为系统初始化就会调用这个函数,默认配置就是这样子,也不要去修改,很多代码都是基于这个基础上面写的。知道哪个设备挂载在哪个线路上面的知识就尤为重要,这也是我写这篇文章的初衷。低功耗的停止模式其实和这个时钟也有一些联系,因为停止模式每次唤醒,都需要执行一下SystemInit函数(手动),因为进入停止模式,高速时钟全关了。需要每次重启一下,之后再进入停止模式。当然你也可以不用,就是会一直以8MHZ的主频执行,就第一次72MHZ,进入之后每一次唤醒都是8MHZ,外部高速时钟唤醒失败,肯定是执行内部的高速时钟。待机模式就不用手动了,不会保存状态,每次唤醒都是重新执行。

  • 上面是起振成功走的路线,然后失败的else,是空的,允许用户做一些编辑,比如起振失败的异常处理。
  • 默认就是一开始配置的内部时钟(HSI),文章上面有提到。很巧妙只能说。

  • 这个也是为什么停止模式需要每次都执行这个SystemInit函数的原因
  • 因为进入停止模式会关闭外部高速时钟,导致起振失败,就会切换内部高速时钟。简单讲,先配置内部高速时钟,然后改变配置,想配置成外部高速时钟,结果外部高速时钟配置失败,只能按照刚刚配置的内部高速时钟来用。

代码我就不贴了,篇幅有点长。

二、BKP

这个部分是为了和RTC联系起来,还有LSE的供电也是有联系。所以把这个知识点也放这。

  • BKP(Backup Registers)备份寄存器
  • BKP可用于存储用户应用程序数据。当VDD(2.0~3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位
  • TAMPER引脚产生的侵入事件将所有备份寄存器内容清除
  • RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲
  • 存储RTC时钟校准寄存器
  • 用户数据存储容量:     20字节(中容量和小容量)/ 84字节(大容量和互联型)
  • 本质其实也是一个RAM存储器,只是多个供电方式,主电源断开,如果备用电源在供电,寄存器内容就会保持着。
  • 系统复位和电源复位,不会复位数据,当然如果全部电源断开,寄存器内容肯定全没了,至少要留下一个电源。
  • 可以给LSE振荡器时钟(通常为32.768KHz)供电

三、RTC

这个知识点,与唤醒有关系,灰色部分是备用的供电

  • RTC(Real Time Clock)实时时钟
  • RTC是一个独立的定时器,可为系统提供时钟和日历的功能
  • RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD(2.0~3.6V)断电后可借助VBAT(1.8~3.6V)供电继续走时
  • 32位的可编程计数器,可对应Unix时间戳的秒计数器
  • 20位的可编程预分频器,可适配不同频率的输入时钟
  • 可选择三种RTC时钟源:     HSE时钟除以128(通常为8MHz/128)     LSE振荡器时钟(通常为32.768KHz)     LSI振荡器时钟(40KHz)
  • 灰色区域就是BKP支持供电的区域
  • 主电源断电相当于电脑关机,那么电脑主板的bios电池维持供电(类似BKP),那么开机,你的时间才对,也不是每次都会自动联网校对时间,都是隔一段时间校对一次时间。
  • 执行以下操作将使能对BKP和RTC的访问:   
  •  1、设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     
  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);        //开启PWR的时钟
  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);        //开启BKP的时钟
  • 2、设置PWR_CR的DBP,使能对BKP和RTC的访问
  • PWR_BackupAccessCmd(ENABLE);    //使用PWR开启对备份寄存器的访问
  • 若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1
  • 必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器
  • 对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器

这个地方需要注意的是,LSE是外部时钟,这个时钟可以是BKP提供供电,当然主电源在的时候也会供电,主电源断电就由BKP供电,这也是我为什么把几个不同模块放一下总结的原因。

四、PWR

  • PWR(Power Control)电源控制
  • PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能
  • 可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务
  • 低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间

一、电源

这个是电源供电的分布,可以看看

  • VDDA(VDD Analog) 模拟部分供电  
  • VDD 数字部分供电 分为两个部分,如上图
  • VBAT 后备供电
  • 使用电池或其他电源连接到 V BAT 脚上,当 V DD 断电时,可以保存备份寄存器的内容和维持 RTC 的功能。

二、上电复位(POR)和掉电复位(PDR)

三、可编程电压监测器(PVD)

四、电源控制寄存器(PWR_CR)

五、电源控制/状态寄存器(PWR_CSR)

五、EXIT

外部中断会涉及到,也拿过来了

  • 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
  • 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
  • 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
  • EXTI(Extern Interrupt)外部中断
  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应

这个是外部中断部分的内容,复习一下

六、NVIC

这个也看看,配置一些优先级用的,一般我们外部中断触发,就会走这个

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
  • 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

三、低功耗模式

描述:在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式

一、模式一览

这个结合上面的电源那个图来记忆。

  • 对于VDD部分,停机模式待机模式会关闭高速时钟(内外时钟都关),但是低速时钟(内外不关)
  • 停机模式待机模式会关闭1.8V区域的时钟(看上面电源的图),关闭的是时钟,不是断电。电压调节器关了,1.8V区域才会断电。所以根据这个,才说待机模式的1.8V区域是断电的。停机模式如果1.8V都断电了,那么寄存器和内存的数据就保持不了了。所以这个是我对这个图的理解,可以结合电压调节器部分,如下

二、电压调节器

如上是手册里面 电压调节器的描述
  • RCC BDCR寄存器,也叫备份域寄存器

这个电压调节器我想应该是三种状态:开启、低功耗、关闭,因为这样子,对应上图的开关以及低功耗就比较合理。这个描述就可以理解了,根据应用的方式提供的例子。因为停机模式,电压调节器可以选择开启和低功耗,低功耗会有一段额外的启动延时。

三、3种模式

如上是手册里面 低功耗模式的描述

睡眠模式(Sleep Mode)

  • 电压调节器状态:保持在正常工作状态。
  • 功耗:相对于运行模式稍低,但仍保持大部分外设的功能。
  • 系统状态CPU 停止,但外设和时钟继续运行。适用于短时间的低功耗需求,快速恢复到运行模式。
  • 执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行(保存资源)
  • SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠
  • 在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态
  • WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
  • WFE指令进入睡眠模式,可被唤醒事件唤醒
  • 这个时候如果发一个UART的信号过来是可以接收的,因为外设时钟是没有关的

睡眠模式的事件唤醒有点麻烦

如手册讲的,两种方式

停止模式(Stop Mode)

  • 电压调节器状态:进入低功耗模式,提供最低限度的电压以保持寄存器和 SRAM 的数据。
  • 功耗:大幅降低,适用于需要保持数据但不需要立即响应的场景。
  • 系统状态:CPU 和大多数外设停止运行,主时钟源关闭。低速时钟(如 LSE、LSI)继续工作。通过外部中断、RTC 或看门狗定时器唤醒
  • 执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行
  • 1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来(保存资源,也意味着需要手动执行SystemInit函数)
  • 在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态 当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟
  • 当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时
  • WFI指令进入停止模式,可被任意一个EXTI中断唤醒
  • WFE指令进入停止模式,可被任意一个EXTI事件唤醒

待机模式(Standby Mode)

  • 电压调节器状态:关闭。
  • 功耗:最低功耗,几乎所有电源都关闭,仅保留唤醒电路
  • 系统状态:所有外设和时钟停止,SRAM 和寄存器内容丢失。通过外部重置、RTC 或独立看门狗定时器唤醒。低速时钟(如 LSE、LSI)不禁止,所以意味着,RTC定时的时钟源可以选择它们,不过需要注意的是LSI仅仅是主电源供电的,LSE的支持备用电源供电。
  • 执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行
  • 整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电(不保存资源,每次唤醒都会默认执行SystemInit函数,所以不用手动)
  • 在待机模式下,所有的I/O引脚变为高阻态(浮空输入)
  • WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式

模式选择

停机模式,电压调节器可以选择开启和低功耗,如下

  •  之后都是一些细节问题了,比如睡眠分为立刻睡眠还有等待中断退出后再睡眠。比如等待一些重要的中断执行结束再进行睡眠。只要不在中断里面调用WFI或者WFE,在主函数调用,效果是一样的。都会等待中断结束,回到主函数再调用WFI或者WFE。主程序执行到了,自然也代表中断执行结束。如果在中断里面调用,如果立刻睡眠,就会被打算,唤醒再继续,选择等待,就是等待中断结束再睡眠。
  • 这个配置没有函数,只能配置寄存器,停机和待机都有可以配置的函数

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据提供的引用内容,STM32F103C8T6可以通过设置PDDS位来使CPU进入待机模式,并且可以通过CWUF位清除之前的唤醒位。RTC外设是一个掉电后仍然运行的定时器,它具有掉电还继续运行的特性。RTC模块可以提供时钟日历的功能,并且可以通过修改计数器的值来重新设置系统的时间和日期。在设置时间之前,需要取消备份区(BKP)的写保护。 下面是一个STM32F103C8T6待机模式RTC唤醒的示例代码[^1][^2]: ```c #include "stm32f10x.h" void RTC_Configuration(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); BKP_DeInit(); RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); RTC_SetAlarm(RTC_GetCounter() + 10); RTC_WaitForLastTask(); EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void RTC_IRQHandler(void) { if (RTC_GetITStatus(RTC_IT_ALR) != RESET) { RTC_ClearITPendingBit(RTC_IT_ALR); // 处理RTC闹钟中断 } } int main(void) { RTC_Configuration(); while (1) { PWR_EnterSTANDBYMode(); } } ``` 这个示例代码中,首先进行了RTC的配置,包括使能PWRBKP外设时钟,取消备份区写保护,配置LSE时钟源,使能RTC时钟,等待RTC同步,使能RTC闹钟中断,设置RTC预分频器和闹钟时间等。然后,初始化外部中断线和中断向量表,并在主循环中进入待机模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的宾哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值