嵌入式知识复习(二)——时间管理(时钟树、RTC、Unix)

一、时钟树:时钟源、锁相环

(1)时钟源

(2)锁相环:

将低频时钟源(如HSE/HSI)倍频至更高频率,生成系统主时钟(SYSCLK)

RCC_PLLConfig(RCC_PLLSource_HSE, RCC_PLLMul_9);  // HSE=8MHz ×9 → SYSCLK=72MHz
(3)时钟树配置关键点

  优先级:HSE > HSI(HSE故障时自动切换至HSI)。

  外设时钟分配

  • APB1(低速总线):最大36 MHz(如定时器TIM2-TIM7)。

  • APB2(高速总线):最大72 MHz(如GPIO、SPI1)。

二、RTC实时时钟

(1)RTC的时钟源选择(LSE/LSI):任选一个接到RTCCLK

  LSE(推荐)

    精度高(月误差约±1秒),需外接32.768 kHz晶振。

    典型应用:需要精准计时的场景(如电子表、数据记录),如计时、日志记录等。

 LSI(备用)

   精度低(误差可达±5%),无需外部元件,40kHz。

   适用场景:成本敏感且对时间精度要求不高的设备,简单的定时器、看门狗定时。

 HSE时钟除以128:

  通常为8MHz/128

(2)RTC掉电时间保持机制
  • BKP寄存器(Backup Registers)

    • 特殊寄存器,由后备电源(VBAT)供电,主电源断开后数据不丢失。

    • 功能:保存RTC配置和计数器值。

  • RTC掉电时间保持机制

    • BKP寄存器(Backup Registers)

      特殊寄存器,由后备电源(VBAT)供电,主电源断开后数据不丢失。

      功能:保存RTC配置和计数器值

    • 后备电源(VBAT)

      • 连接纽扣电池(如CR2032)至VBAT引脚,确保RTC和BKP寄存器在断电时持续供电。

(3)RTC操作事项
  • 执行以下操作将使能对BKP和RTO的访问:

    设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟

    设置PWR_CR的DBP使能对BKP和RTC的访问

  • 若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1

  • 必须设置RTC_CRL寄存器中的CNP位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器

  • 对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器

三.Unix时间戳

从1970年1月1日00:00:00 UTC至今的秒数

  • 时间戳存储在一个秒计数器中,秒计数器位32位/64位的整型变量(32位整数,2038年溢出

  • 世界上所有时区秒计数器相同,不同时区通过添加偏移来得到当地时间

  • Unix时间戳基于UTC,需根据本地时区调整(如东八区:unix_time += 8*3600

  • Unix时间戳与RTC时间的转换(闰年、时区处理)

// RTC时间(年月日时分秒)转Unix时间戳
uint32_t rtc_to_unix(RTC_DateTypeDef date, RTC_TimeTypeDef time) {
    struct tm t;
    t.tm_year = date.Year + 100;  // tm_year=实际年份-1900(RTC Year从2000开始)
    t.tm_mon = date.Month - 1;    // tm_mon=0~11
    t.tm_mday = date.Date;
    t.tm_hour = time.Hours;
    t.tm_min = time.Minutes;
    t.tm_sec = time.Seconds;
    return mktime(&t) - timezone * 3600;  // 校正时区
}
​
// Unix时间戳转RTC时间
void unix_to_rtc(uint32_t unix_time, RTC_DateTypeDef *date, RTC_TimeTypeDef *time) {
    struct tm *t = gmtime(&unix_time);  // 使用UTC时间
    date->Year = t->tm_year - 100;      // RTC Year从2000开始
    date->Month = t->tm_mon + 1;
    date->Date = t->tm_mday;
    time->Hours = t->tm_hour;
    time->Minutes = t->tm_min;
    time->Seconds = t->tm_sec;
}

四、常见问题
1.RTC如何实现掉电时间保持(BKP寄存器的作用)?
  • BKP寄存器:存储RTC计数器值和配置,由VBAT供电,主电源断开后数据保留。

  • 后备电源(VBAT):连接纽扣电池至VBAT引脚,确保RTC和BKP持续工作。

  • 在系统初始化时,会对 RTC 进行配置并启动计时。RTC 的计时数据(如年、月、日、时、分、秒)会不断更新,同时可以将这些数据存储到 BKP 寄存器中。当主电源掉电时,备份域的电源继续为 RTC 和 BKP 寄存器供电,RTC 继续计时,BKP 寄存器中的数据也得以保存。当主电源恢复后,系统可以从 BKP 寄存器中读取之前保存的时间数据,继续进行时间的显示和处理。

    // 初始化RTC并启用BKP
    HAL_PWR_EnableBkUpAccess();  
    __HAL_RCC_BKP_CLK_ENABLE();
2.Unix时间戳溢出问题(2038年问题)如何解决?
  • 升级到64位时间戳:64位整数可表示时间至约2920亿年后。

  • 使用无符号32位整数:延后溢出时间至2106年,但需系统支持。

  • 采用新的时间标准:可以考虑采用新的时间标准来替代 Unix 时间戳,例如 ISO 8601 标准,它使用字符串来表示日期和时间,不存在溢出问题,并且具有更好的可读性和跨平台兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值