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)由后备域复位。
使用LSI驱动RTC的问题:
STM32的LSI频率40KHZ,网友实测在30-60KHz间波动,一个小时会有1分钟左右的偏差。LSI断电的时候,不在后备供电区域范围内,而外接的3.3V电池连接到VBAT上只给后备供电区域供电,导致电池只能维持后备RTC的计数,并无法维持LSI,RTC不继续运行只保持断电前的时间。重新上电后需要重新校准。
RTC的时钟源一经确定不能改变,除非备份域复位才能重新设置其他时钟源如LSE。
HAL_RTC_AlarmIRQHandler(&hrtc); //事件中断
HAL_RTCEx_RTCIRQHandler(&hrtc); //秒中断