STM32->RTC

STM32在更大范围内的时间控制,就不能再使用Delay()函数和tim了,是吧?

    RTC(Real Time Clock)实时时钟单元,即使系统电源关闭,可以通过备用电池供电继续工作。RTC 可以通过STRB/LDRB这两个ARM指令向CPU传送8位数据(BCD码),这些BCD 数据包括秒、分、时、日期、星期、月和年信息。RTC单元可以通过一个外部的32.768kHz晶振提供精确的时钟。每一个周期信号到来计数器就加1。

    RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。但在实际使用中,通常MCU复位就会导致RTC时间丢失。因为RTC也需要备份,然后在复位后读出备份日期。(BKP->DR寄存器数量有限哦)

    if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0x32F2){....

    HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1,0x32F2);}

或者用STLib:

    if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){....       

    BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);}                 // 寄存器:BKP->DR1=0xA5A5;

    备份域可以通过软件复位,RCC的BDCR寄存器BDRST位置1;也会在VDD和VBAT两者都掉电时复位。所以在检测到后备寄存器有特定值得情况下就排除了VDD和VBAT两者都掉电的情况,反之就需要初始化RTC了。BKP->DRx寄存器不会被系统复位、电源复位、从待机模式唤醒所复位,它们由备份域复位来复位或(如果侵入检测引脚TAMPER功能被开启时)由侵入引脚事件复位。RTC的核心寄存器(RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV)由后备域复位。

STM32->RTC

STM32->RTCSTM32->RTC


使用LSI驱动RTC的问题:

     STM32的LSI频率40KHZ,网友实测在30-60KHz间波动,一个小时会有1分钟左右的偏差。LSI断电的时候,不在后备供电区域范围内,而外接的3.3V电池连接到VBAT上只给后备供电区域供电,导致电池只能维持后备RTC的计数,并无法维持LSI,RTC不继续运行只保持断电前的时间。重新上电后需要重新校准。
    RTC的时钟源一经确定不能改变,除非备份域复位才能重新设置其他时钟源如LSE。


关于RTC中断:
   一般使用到RTC的秒中断和闹钟中断,例如在HAL库中:
    HAL_RTC_SetAlarm_IT(&hrtc,sAlarm,RTC_FORMAT_BCD);
    HAL_RTCEx_SetSecond_IT(&hrtc);
    都会进入到 RTCAlarm_IRQHandler()中,如果没有处理直接放处理函数:
    HAL_RTC_AlarmIRQHandler(&hrtc);        //事件中断
    HAL_RTCEx_RTCIRQHandler(&hrtc);        //秒中断
    在ST库中实现的话在从RTC_IRQHandler()退出会清除所有中断标志,秒中断会导致清理闹钟中断标记,需要有不同的中断优先级。但在HAL中的中断处理函数会先判断中断标记,并包裹在if中完成相应的操作,所以没有遇到这个问题。

    调用sAlarm->AlarmTime=(RTC_TimeTypeDef)stimestructure和 HAL_RTC_SetAlarm_IT(&hrtc,sAlarm,RTC_FORMAT_BCD);,就会进入HardFault_Handler。调试发现错误出现在LDRB  r0这条汇编指令上。
STM32->RTC