0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32片内RTC亚秒特性以及应用演示的分享

茶话MCU 来源:茶话MCU 2023-04-15 11:27 次阅读

绝大多数STM32系列里的RTC都具有亚秒【或称子秒】计数单元。为了了解亚秒特性及功能,不妨先看RTC的功能框图。本文中的有关截图若无特别说明均来自STM32L4系列参考手册。

poYBAGQ6GieAQOEaAAFB4__3keE403.jpg
pYYBAGQ6Gi-AE1UnAAFCexBdT7M099.jpg

RTC的时钟源【RTCCLK】可以是LSE、LSI或者HSE/32,由RTCCLK最终变成日历的秒脉冲驱动信号经过了2次分频。先经过上图中A处的异步分频单元,默认分频系数是128,形成ck_apre时钟,默认情况下该时钟频率为256Hz;然后该时钟脉冲来到图中B处的同步分频单元,默认分频系数为256,最终形成1Hz的秒脉冲【ck_spre】到日历单元。关于两分频单元分频系数的配置,通过对RTC_PRER寄存器的相关位编程实现。

poYBAGQ6GkKAK6boAACiM741gNw674.jpg

其中异步分频系数配置位【PREDIV_A】有7位,同步分频系数【PREDIV_S】有15位。另外,同步分频单元还包括采用向下计数方式的亚秒计数器,它基于异步分频后的时钟ck_apre进行计数,溢出时的重装值等于PREDIV_S。一般来讲,它的一个计数周期就是1s,其计数分辨率或精度为【1/(PREDIV_S+1)】秒。与之配套的亚秒寄存器,实时记录亚秒计数器的计数值,有效数据位乃16位,比PREDIV_S多1位,多出的1位另有它用,此处不表。

pYYBAGQ6GlaAc5OrAAEKYCvNCrM211.jpg

显然,当有了这个亚秒计数器后,我们就可以获得少于1秒的时间,或说秒的小数部分---亚秒,其精度由同步分频系数PREDIV_S决定,某时刻的亚秒数通过亚秒寄存器获取,对应的亚秒时间可以通过上图中第2个红色方框内的算式求得【提醒:亚秒计数器采用向下计数方式】。

关于RTC的亚秒概念及基本特性就介绍到这里。稍微小结下:

1、亚秒是对少于1秒的时间称谓,范围在0到1秒,并非固定的值;

2、亚秒精度【分辨率】可调,由PREDIV_S参数决定,即【1/(PREDIV_S+1)】秒;

3、亚秒寄存器【RTC_SSR】实时记录亚秒计数器的值,具体由SS[15:0]体现;

3、亚秒时间通过算式(PREDIV_S-SS/(PREDIV_S+1)求得;

我们知道RTC除了提供基本的日历功能外,还有很好的低功耗特性,常用于低功耗的唤醒。有些低功耗应用场合,虽然系统需要周期性的唤醒,但对唤醒周期的一致性要求往往并不严格、很多时候的周期值往往远达不到秒级,比方在10个毫秒上下、几十个毫秒左右、100毫秒量级不等。像这种场合,我们可以考虑使用RTC的亚秒特性和ALARM功能实现周期性唤醒。

假设某STM32用户有这样的需求,他的系统涉及低功耗,需要周期性地做休眠与唤醒的切换。他希望系统进入休眠后每隔50±20ms的时间范围内被唤醒,唤醒后做些基本的检测处理后又进入休眠。要实现这个需求,对于很多带LPTIM的STM32系列也很方便实现。

不过,今天主要想聊聊如何通过RTC来实现该需求。了解STM32的RTC的人可能知道,RTC模块往往还自带一个专门的16位向下计数的唤醒定时器,即下面RTC局部框图中红框所在单元。我这里要分享的也不是这个专用唤醒定时器,而是想基于ALARM事件和亚秒特性来实现上面需求。

pYYBAGQ6Gm2AGG9FAAFQYQ7Jhxo979.jpg

对于RTC的ALARM功能我们都不陌生,即先预设需要ALARM的时间点,当日历时间跟设定的ALARM时间匹配时就可以触发ALARM事件及中断。对于ALARM时间点的报警条件可以有很多灵活的组合配置,比方我们可以设置在某月某日某时某分某秒ALARM,也可以设置在某分某秒ALARM,其它不关心,或者仅设置在某个亚秒时刻ALARM,其它不关心。

poYBAGQ6Gn-AFrXwAAFnNfyYHn4504.jpg

上图中四种ALARM设置,灰色部分表示不关心项,即不参与日历值与ALARM设定值相关项的比较。这里分别表示的警情时刻是:

第一种,只要日历中跟ALARM设置的时、分、秒匹配时报警,其它不关心;

第二种,只要日历中跟ALARM设置的分值、秒值匹配时报警,其它不关心;

第三种,只要日历中跟ALARM设置的秒值和亚秒低3位值匹配时报警,其它不关心;

第四种,只要日历中跟ALARM设置的亚秒的低4位值匹配时报警,其它不关心;

我们回到前面提到的需求,每隔50±20ms做唤醒,即30ms~70ms范围内实现唤醒都可以接受。如果说使用ALARM中断,相信很多人自然会想到,先设定一个ALARM点,等唤醒后再修改新的ALARM值,就这样延续下去。

poYBAGQ6GpKAJVyOAAAmdBjRTOo485.jpg

这样操作也是可以的,即每次在ALARM中断里修改新的ALARM时间点。下图是对ALARM值进行编程的流程【设置时先要关闭ALARM,修改ALARM值后再手动开启ALARM单元】:

poYBAGQ6GqKAG4t2AAD1LaORre0332.jpg

不过,结合眼前的应用需求,我们可以不使用上面的做法,而是巧妙地使用RTC亚秒特性来实现周期性的ALARM以满足需求。怎么个巧法呢?一起来看看。

先假定RTCCLK为32768Hz,RTC同步分频系数和异步分频系数分别为如下参数:

PREDIV_A=127,PREDIV_S=255。

pYYBAGQ6GriAFZimAACLksb3lOQ608.jpg

依据现有的分频配置,则亚秒的时间精度或者说分辨率为(1/256)秒,3.9ms的样子,即亚秒计数器每计1个脉冲所对应的时间就是3.9ms,算4ms吧。【记住这个数据后面要用】

谈到这里,我们跳跃一下思路,换个数学话题聊聊。【注:这个地方可能有点突兀。突兀的突悟往往离不开艰辛的修行。】

这里有从0开始按照从小到大排列的一批足够多的自然数列,按10进制展现。我们来看看几种情形:

1、如果找出只要个位数相同的数据,仍然按照从小到大排列,每相邻两个数的差值一定是10。对不对?

2、如果找出只要个位数与十位数都相同的数据,仍然按照从小到大排列,每相邻两个数的差值一定是100。没错吧。

3、如果找出只要个位数与十位数以及百位数都相同的数据 仍然按照从小到大排列,每相邻两个数的差值一定是1000。结论也没问题。

。。。。。。

到此,我们应该发现规律了,通过关注低几位数相同而重新有序排列而成的相邻数据之差即为10的几次方,其实这里相邻数的差值也就是原自然数列中两个数的位置间隔。【注意关键词:位数,数据,相邻】我们可以基于下图的一批十进制数据表格做些直观的观察。

pYYBAGQ6GsmAXsOSAAGRHjqhMi4969.jpg

好,我们不妨改变下数据的进制看看。还是从0开始按照从小到大排列的一批足够多的自然数列,按2进制展现。依然看看几种情形并得出相应结论。

1、若找出只要低1位数相同的数据,仍按照从小到大排列,每相邻两个数的差值一定是2;

2、若找出只要低2位数都相同的数据,仍按照从小到大排列,每相邻两个数的差值一定是4;

3、若找出只要低3位数都相同的数据 仍按照从小到大排列,每相邻两个数的差值一定是8;

其它我们可以依次类推。

同样,我们也发现规律,通过关注二进制数的低几位相同而重新有序排列而成的相邻数据之差即为2的几次方。我们可以基于下图的一批二进制数据表格做些直观的观察。【橙色代表低2位相同的数据,绿色代表低3位相同的数据,红色代表低4位相同的数据】

pYYBAGQ6GtiAKrSvAADfP5g64SY156.jpg

上面专门聊了一段纯数学话题,继续回到我们的亚秒应用问题。

我们知道,包括亚秒在内的整个日历数据实质上是个具有高低顺序和进位关系的数据,其中,亚秒是整个日历数据里的最低端。当我们设置ALARM参数时,如果说只关注亚秒的低1位,其它都不关心。基于前面的数学话题铺垫可知,每当出现低1位数据相同的两个相邻数,总是相差2个计数单位,这里就是2个计数脉冲。换言之,每隔2个计数脉冲,结合前面分析,即每隔8ms都会触发ALARM事件。

如果说只关注亚秒的低2位,其它都不关心,那么每当出现低2位数据相同的相邻数,总是相差4个计数单位,即4个计数脉冲。换言之,每隔4个计数脉冲,即16ms都会触发ALARM事件。

如果只关注亚秒的低3位,其它参数都不关心,每当出现低3位数据相同的相邻数,总是相差8个计数单位,即8个计数脉冲,每隔32ms都会触发ALARM事件。

其它依此类推。

谈到这里,设置的只关心亚秒的位数跟ALARM周期的关系应该说很清晰了。我在下面简单罗列了基于前面条件下亚秒的关心位数与ALARM周期的对应表:【灰色表示不关心,不参与日历值与ALARM设定值的比较,只有绿色位参与比较】

poYBAGQ6GumAAbIRAAGMq6uz57k185.jpg

现在期望的唤醒周期是50±20ms,我们配置亚秒计数器的低3位或者低4位作为ALARM的比较位【说关心位、参与位什么的都可以】,其它设置为不关心就可以满足要求。我们不妨选择亚秒计数值的低4位参与比较,即每两次相邻ALARM相差16个计数脉冲,周期约为64ms。

下面是我使用CubeMx进行的日历和ALARMA的配置,重点看下ALARM配置。

poYBAGQ6GwCATEdvAAFCKou9yKM926.jpg

这里的ALARM配置只选择亚秒的低4位参与比较,既然这样其它参数就无所谓了。其中那个用于比较的亚秒值我这里写的12,这个值写多少并不影响ALARM周期的拟定,只会影响每次发生ALARM事件时的亚秒计数器的低4位的值。其实,当我们选定只关心亚秒计数器的低4位时,重复ALARM的周期就已经定了。

完成配置、建立工程、组织测试代码。

我在ALARM中断里读取每次发生ALARM事件时的亚秒值。我截取几个连续ALARM事件的相关信息在如下几幅图。其中变量Sub_Value和stime1.SubSeconds是一个东西,表示发生ALARM事件时亚秒计数器的值。比如下面各截图中的236、220、204、188、172、156几个数,显然两相邻数的间隔保持准确的16个计数脉冲,若把这几个数转成2进制,他们的低4位都是1100B,即我在前面ALARM设置的亚秒比较值12

poYBAGQ6Gy2AJPXXAAErzREEWzI139.jpg
pYYBAGQ6GzSAL8MeAAET6ayDZpM703.jpg
poYBAGQ6GzqANsmWAAEeb2LIODY396.jpg
pYYBAGQ6G0GAb1T-AAEfbe0Wdz8748.jpg
pYYBAGQ6G1OASzzRAAGKE8MZMLY567.jpg

若在每次的ALARM中断里把发生ALARM的时间点实时打印出来,可以清晰地看到相邻两次ALARM事件的时间间隔固定在63ms左右,这个值跟前面规划的基本一致。

pYYBAGQ6G2KADofaAAFBYky29_E202.jpg

有人或许会问,相邻ALARM事件的时间差为什么没有计数脉冲数差值那样稳定精准。我认为主要有两点原因,一是我测试时并没有使用标准的32768外部时钟,而是选择的内部LSI,它的频率一般在31Khz到33KHz之间,不像LSE那么精准。还有一个原因,在做亚秒时间计算时,因为无法整除原因肯定会带来计算偏差。

利用上面方法可以省去每次修改ALARM配置的操作,类似这种具有周期性且周期不大于1秒的应用都可以尝试考虑上述方法,必要的时候可以考虑调整同步分频系数即亚秒计数器的重装值以满足具体的时间精度要求。当然,调整同步分频系数的同时往往要调整异步分频系数,原则上异步分频系数要尽量大以充分降低RTC模块带来的功耗,具体应用时我们可以综合考虑后再做调整。




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348744
  • LSE
    LSE
    +关注

    关注

    0

    文章

    10

    浏览量

    10169
  • RTC
    RTC
    +关注

    关注

    2

    文章

    484

    浏览量

    65439
  • 时钟源
    +关注

    关注

    0

    文章

    87

    浏览量

    15770
  • 时钟脉冲
    +关注

    关注

    0

    文章

    19

    浏览量

    12554

原文标题:巧用STM32片内RTC亚秒特性之应用示例

文章出处:【微信号:stmcu832,微信公众号:茶话MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    stm32L476RG RTC中断如何使用?

    stm32L476RG RTC中断如何使用
    发表于 04-26 08:24

    stm32利用RTC在tamper引脚上输出脉冲

    芯片用的是STM32F103VBT6,目前程序已经可以在tamper(PC13)引脚上输出校正时钟,其时钟频率为RTC时钟除以64。但调了好几天都无法输出脉冲,求大神搭救
    发表于 10-14 21:47

    转:XMEGA学习记录——抽筋扒皮彻查RTC32

    _get_time();---------------------------------------------------------------------------------------------------简单测试一下,读到的RTC32计数器的值为0xC05,因为我断电了一段时间,
    发表于 07-28 15:04

    关于RTC中断功能

    RTC(Real Time Clock)是实时时钟的意思,它其实和TIM有点类似,也是利用计数的原理,选择RTC时钟源,再进行分频,到达计数的目的。该文主要讲述关于RTC中断功能,
    发表于 08-13 06:57

    关于RTC中断功能

    Ⅰ、概述RTC(Real Time Clock)是实时时钟的意思,它其实和TIM有点类似,也是利用计数的原理,选择RTC时钟源,再进行分频,到达计数的目的。该文主要讲述关于RTC
    发表于 08-16 08:19

    STM32CubeMX RTC简介

    包含二进码十进数格式 (BCD) 的、分钟、小时( 12 或 24 小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的值。系统可以自动将月份的天数补偿为 28、29(闰年)、30
    发表于 08-18 06:37

    STM32FLASH操作步骤

    STM32FLASH可分为哪几类?如何去使用STM32FLASH呢?
    发表于 11-01 06:36

    STM32FLASH该如何去使用呢

    STM32FLASH可分成哪几部分?STM32的FLASH共有几个键值呢?
    发表于 11-02 07:08

    怎么实现STM32F10x_RTC中断?

    怎么实现STM32F10x_RTC中断?
    发表于 11-16 08:15

    STM32RTC简介

    STM32RTC学习笔记Mcu:STM32F103RBT61、RTC简介RTC(Real Time Clock)实时时钟,是
    发表于 03-01 06:47

    具有带32位唤醒计数器的RTC的超低MCU有哪些

    我目前正在使用 STM32WLE5CC MCU,它具有带 32 位唤醒计数器的 RTC 的强大功能,但我的其他非 lorawan 项目需要一个低成本的 MCU,它也需要这个“带 3
    发表于 12-02 06:14

    如何实现STM32 RTC时间之间的差异在10左右?

    时间和 stm32 RTC 时间之间的差异时间是 10 STM32 RTC时间每1分钟慢10
    发表于 01-11 06:46

    STM32片内RTC亚秒特性的应用示例(上)

    绝大多数STM32系列里的RTC都具有亚秒【或称子秒】计数单元。为了了解亚秒特性及功能,不妨先看RTC的功能框图。本文中的有关截图若无特别说明均来自
    的头像 发表于 04-30 16:28 671次阅读
    <b class='flag-5'>STM32</b>片内<b class='flag-5'>RTC</b>亚秒<b class='flag-5'>特性</b>的应用示例(上)

    STM32片内RTC亚秒特性的应用示例(下)

    不过,今天主要想聊聊如何通过RTC来实现该需求。了解STM32RTC的人可能知道,RTC模块往往还自带一个专门的16位向下计数的唤醒定时器,即下面
    的头像 发表于 04-30 16:32 1129次阅读
    <b class='flag-5'>STM32</b>片内<b class='flag-5'>RTC</b>亚秒<b class='flag-5'>特性</b>的应用示例(下)

    STM32系列里RTC的亚秒特性及功能(上)

    绝大多数STM32系列里的RTC都具有亚秒【或称子秒】计数单元。为了了解亚秒特性及功能,不妨先看RTC的功能框图。本文中的有关截图若无特别说明均来自
    的头像 发表于 06-21 15:53 1755次阅读
    <b class='flag-5'>STM32</b>系列里<b class='flag-5'>RTC</b>的亚秒<b class='flag-5'>特性</b>及功能(上)