拓冰建站拓冰建站
首页 / 资讯中心 / 正文

MicroPython pyb.RTC 实时时钟深入指南:日期时间读写、唤醒定时器与平滑校准

MicroPython pyb.RTC 实时时钟深入指南日期时间读写、唤醒定时器与平滑校准【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropythonpyb.RTC是 MicroPython 在 STM32 系列开发板pyboard上提供的实时时钟Real Time Clock接口它由硬件 RTC 外设驱动与主系统时钟相互独立能够在主 CPU 停机甚至整板待机standby期间持续记录日期与时间。本文以 docs/library/pyb.RTC.rst 为骨架结合 ports/stm32/rtc.c 的实现细节系统讲解 RTC 的构造、datetime()日期时间读写、wakeup()周期唤醒、info()启动信息以及calibration()频率校准并给出可在 pyboard 上直接运行的可验证示例。读完本文你将能够用几行 Python 代码完成时间戳管理、低功耗定时唤醒和时钟漂移校正。RTC 是什么RTC 是一个独立于主 CPU 的时钟外设专门负责跟踪日期与时间。在 STM32 平台上RTC 通常由以下两种时钟源之一驱动LSE外部低速晶振典型 32768 Hz精度高断电后由 VBAT 备份电池维持走时适合长期计时LSI内部低速 RC 振荡器标称 32000 Hz无需外部晶振但精度略低。从源码结构看ports/stm32/rtc.c 中通过RTC_ASYNCH_PREDIV/RTC_SYNCH_PREDIV及其_LSE、_LSI变体配置分频系数把时钟源分频到 1 Hz 的秒脉冲ck_spre这些值可以在各开发板的mpconfigport.h中按需调整。RTC 一旦运行便持续计数即使进入pyb.stop()Stop 模式或pyb.standby()Standby 模式也不会停止。快速上手文档给出的最小示例非常简洁import pyb rtc pyb.RTC() rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0)) # 设置时间 print(rtc.datetime()) # 读取时间pyb.RTC()构造器不接收任何参数它返回一个代表板载 RTC 外设的单例对象源码中由pyb_rtc_obj常量对象实现见 ports/stm32/rtc.c。同一时刻多次调用pyb.RTC()得到的都是同一个底层硬件。datetime()日期与时间的读写RTC.datetime([datetimetuple])是 RTC 最核心的接口兼具读取与设置两种用途无参数调用返回当前日期与时间的 8 元组传入 1 个 8 元组设置日期与时间同时将subseconds重置为 255。8 元组的完整格式为(year, month, day, weekday, hours, minutes, seconds, subseconds)字段说明字段取值范围说明year2000–2099完整年份month1–12月份day1–31日weekday1–71 为星期一7 为星期日hours0–2324 小时制minutes0–59分seconds0–59秒subseconds255→0 倒数亚秒计数设置时间后被重置为 255关于weekday需要特别留意它遵循1Monday, 7Sunday的约定与 Python 标准库datetime.weekday()0Monday不同跨库换算时要小心偏移。读写实现原理在 ports/stm32/rtc.c 的pyb_rtc_datetime中可以看到读取时先调用HAL_RTC_GetTime再调用HAL_RTC_GetDate源码注释明确说明必须按此顺序访问寄存器才能正确读取影子寄存器中的一致值年份在内部以相对于 2000 的偏移量存储date.Year mp_obj_get_int(items[0]) - 2000读出时再加回 2000因此有效年份范围为 2000–2099subseconds来自 RTC 的同步分频计数寄存器读出后经rtc_subsec_to_us换算而设置时间时该值被硬件复位逻辑重置。实用的读写模式from pyb import RTC rtc RTC() # 设置时间2024 年 6 月 15 日星期六10:30:45 rtc.datetime((2024, 6, 15, 6, 10, 30, 45, 0)) # 读取并解包 year, month, day, weekday, hh, mm, ss, subsec rtc.datetime() print(f{year}-{month:02d}-{day:02d} {hh:02d}:{mm:02d}:{ss:02d}) # 只需 1 秒精度的格式化时间 now rtc.datetime()[:7]在 tests/ports/stm32/rtc.py 中MicroPython 官方测试覆盖了从(2000,1,1)到(2099,12,31)的多种日期边界月末、年末、闰年等并验证了设置后 1.05 秒再读取、前 7 个字段准确递增 1 秒的行为说明datetime()具备完整的日历计算能力。wakeup()周期唤醒定时器RTC.wakeup(timeout, callbackNone)用于设置一个周期性触发的唤醒定时器每经过timeout毫秒触发一次。该触发既可以唤醒pyb.stop()暂停的 CPU也可以唤醒pyb.standby()待机的整板——这是构建低功耗定时采样系统的关键能力。调用规则timeoutNone禁用唤醒定时器提供callback时每次触发都会执行该回调回调必须恰好接收 1 个参数MicroPython 会传入内部唤醒源编号。from pyb import RTC, LED rtc RTC() def tick(n): LED(1).toggle() # 每次唤醒翻转一次 LED示意被唤醒了 # 每 2 秒唤醒一次配合 pyb.stop() 使用可大幅省电 rtc.wakeup(2000, tick) while True: pyb.stop() # 进入 Stop 模式等待 RTC 唤醒毫秒到硬件寄存器的换算唤醒超时最终要落到 STM32 RTC 的 WUTRWakeup Timer Register计数器和 WUCKSEL 时钟选择位。在 ports/stm32/rtc.c 的pyb_rtc_wakeup中毫秒值被自动换算小超时使用 RTC 时钟分频32768 Hz 的 1/16、1/8、1/4、1/2wucksel依次选择更粗的分频得到接近毫秒级的触发间隔大超时切换到 1 Hz 秒时钟wut ms / 1000若wut超过 16 位寄存器上限0x10000会尝试用wucksel6的偏移技巧扩容仍超出范围则抛出ValueError源码中的wakeup value too large对应测试tests/ports/stm32/rtc.py中set_and_print_wakeup(0x20001 * 1000) # exception一行。测试文件同时用stm.mem32[stm.RTC stm.RTC_CR]直读寄存器验证了 0/1/4000/8000/16000/32000 ms 等边界值下 WUCKSEL 与 WUT 的组合说明换算逻辑覆盖了从毫秒级到数万秒的宽范围。与 machine 模块的联动wakeup()并不只属于pyb模块。在 ports/stm32/modmachine.c 中machine.lightsleep(ms)与machine.deepsleep(ms)在收到毫秒参数时都会内部调用pyb_rtc_wakeup来配置 RTC 唤醒随后分别进入 Stop 模式与 Standby 模式而 ports/stm32/modpyb.c 将pyb.stop映射到machine_lightsleep、pyb.standby映射到machine_deepsleep。因此以下写法在 STM32 上等价# 方式一pyb 风格 pyb.RTC().wakeup(5000) pyb.stop() # 5 秒后被唤醒 # 方式二machine 风格 import machine machine.lightsleep(5000) # 内部自动配置 RTC 唤醒info()启动耗时与复位来源RTC.info()返回一个整数用于诊断 RTC 的启动过程与系统复位来源其位定义如下位域含义低 16 位0xffffRTC 启动耗时单位毫秒0x10000置位表示发生过上电复位power-on reset0x20000置位表示发生过外部复位external resetfrom pyb import RTC info RTC().info() startup_ms info 0xffff # 启动花了多少毫秒 was_power_on_reset bool(info 0x10000) was_external_reset bool(info 0x20000) print(startup:, startup_ms, ms)这些信息来自 ports/stm32/rtc.c 中直接返回的内部变量rtc_info。该变量在 RTC 初始化阶段被逐步填充rtc_init_finalise中通过__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)与RCC_FLAG_PINRST检查复位标志并置位对应比特ports/stm32/rtc.c同时记录HAL_GetTick() - rtc_startup_tick作为启动毫秒数。此外源码中还包含 LSE 启动失败回退 LSI、LSEBYP 回退等内部位如0x01000000、0x02000000、0x100000、0x20000000等可用于更深入的硬件诊断。calibration()平滑校准时钟精度晶振频率存在温漂与个体差异长时间运行后 RTC 会累积可观的走时误差。RTC.calibration(cal)提供平滑校准Smooth Calibration机制无参数返回当前校准值范围[-511, 512]的整数带 1 个参数写入校准值超出范围抛出ValueError。校准的物理含义源自文档可由 ports/stm32/rtc.c 的HAL_RTCEx_SetSmoothCalib调用印证STM32 在32 秒2^20 个 32768 Hz 时钟节拍周期内按校准值增删时钟节拍。每增加 1 个节拍时钟加快约 1/2^20即0.954 ppm负值则减慢。因此整个可用校准范围约为最快512 × 0.954 ≈ 488.5 ppm最慢-511 × 0.954 ≈ -487.5 ppm1 ppm 相当于每天约 0.0864 秒因此 ±488 ppm 大约能补偿每天 ±42 秒级别的漂移足以应对绝大多数晶振误差。from pyb import RTC rtc RTC() print(rtc.calibration()) # 读取当前校准值例如 0 # 假设实测时钟每天慢 3 秒则需要正向补偿 # 3 秒/天 ≈ 34.7 ppm ≈ 36.4 个节拍 rtc.calibration(36) # 反向时钟偏快则用负值 rtc.calibration(-20)几点使用注意校准值写入后立即生效且写入新值会覆盖旧值tests/ports/stm32/rtc.py 依次测试了 512、511、345、1、0、-1、-123、-510、-511 等边界值并先保存再恢复原校准值验证了全量程的读写往返一致性部分开发板若定义了MICROPY_HW_RTC_USE_CALOUT源码还支持用0x0ffe/0x0fff特殊值开关 PC13 上的 512 Hz 校准方波输出用于配合外部频率计测量普通用户无需关注。综合实战低功耗定时记录器将上述接口组合起来即可实现一个典型的低功耗应用——每 10 秒唤醒一次记录当前时间戳from pyb import RTC, LED import pyb rtc RTC() log [] def on_wakeup(n): t rtc.datetime() log.append(t[:7]) # (y, m, d, wd, h, m, s) LED(1).toggle() rtc.datetime((2024, 1, 1, 1, 0, 0, 0, 0)) # 初始化基准时间 rtc.wakeup(10000, on_wakeup) print(entering stop mode; will wake every 10s) while len(log) 3: pyb.stop() # Stop 模式下 RTC 继续走时 print(log) rtc.wakeup(None) # 停止唤醒要点回顾wakeup(None)关闭定时器避免进入 Stop 后反复被唤醒pyb.stop()期间 RTC 保持计时唤醒后datetime()读数连续若需跨掉电保持时间请确保开发板使用 LSE VBAT 备份电源配置见各板mpconfigport.h中的MICROPY_HW_RTC_USE_LSE。小结与延伸阅读pyb.RTC在四个方法内覆盖了实时时钟的全部核心需求datetime()负责日历时间的读写wakeup()将低功耗与定时唤醒结合info()提供启动与复位诊断calibration()则以 ppm 级精度校正长期漂移。由于 STM32 的machine模块复用同一实现pyb与machine两种风格可以无缝混用。如需进一步深入建议阅读模块文档docs/library/pyb.RTC.rstSTM32 端口实现ports/stm32/rtc.c、ports/stm32/rtc.h官方回归测试tests/ports/stm32/rtc.py含边界日期、校准全量程、唤醒寄存器换算通用machine.RTC行为测试tests/extmod/machine_rtc.py睡眠模式入口ports/stm32/modmachine.c 与pyb.stop/pyb.standby映射 ports/stm32/modpyb.c其他端口的 RTC 用法可参考 tests/ports/renesas-ra/rtc_init.py、tests/ports/cc3200/rtc.py【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门