获取RTC时间(精确到毫秒)
本文记录一下做项目时的一些经验——基于STM32F429开发板的RTC获取时间,精确到毫秒。
RTC相关寄存器
STM32F429 的RTC(Real_Time Clock)是一个独立的 BCD 定时器/计数器,提供一个日历时钟(包含年月日时分秒信息)、两个可编程闹钟(ALARM A 和 ALARM B)中断,以及一个具有中断功能的周期性可编程唤醒标志。 RTC 还包含用于管理低功耗模 式的自动唤醒单元。两个 32 位寄存器(TR 和 DR)包含二进码十进数格式 (BCD) 的秒、分钟、小时(12 或24 小时制)、星期、日期、月份和年份。此外,还提供一个32位寄存器SSR用于亚秒值(毫秒)。下面主要介绍这三个寄存器。
TR寄存器
存储时间(时、分、秒),其结构下图所示(参考开发手册)
这个寄存器比较简单,注意数据保存时 BCD 格式的,读取之后需要稍加转换,才是十进制的时分秒等数据,在初始化模式下,对该寄存器进行写操作,可以设置时间。
DR寄存器
同样,该寄存器的的数据采用 BCD 码格式,在初始化模式下,对该寄存器进行写操作,可以设置日期。
SSR寄存器
亚秒寄存器,读取寄存器的值并按照公式进行转换即得到毫秒。
式子中的PREDIV_S为RTC配置的同步分频值,源码中初始化函数内可以找到,这里为0X3FF。式子中的SS为亚秒值,直接读取SSR寄存器即可获得。将值代入公式中得出:
( PREDIV_S - SS ) / ( PREDIV_S + 1 ) * 1000
= (3FF - SS )/( 3FF+ 1 ) * 1000
代码
话不多说直接上代码:
rtc.c源文件
需要修改初始化函数中的异步分频值为0X1F,同步分频值为0X3FF,使时间精确到1ms
u8 RTC_Init(void)
{
...
//设置同步0X3FF异步0X1F可以精确到1ms
RTC->PRER=0X3FF;//RTC同步分频系数(0~7FFF),必须先设置同步分频,再设置异步分频,Frtc=Fclks/((Sprec+1)*(Asprec+1))
RTC->PRER|=0X1F<<16;//RTC异步分频系数(1~0X7F)
...
}
//获取RTC时间
//*hour,*min,*sec:小时,分钟,秒钟
//*ampm:AM/PM,0=AM/24H,1=PM.
void RTC_Get_Time(u8 *hour,u8 *min,u8 *sec,u16 *msec,u8 *ampm)
{
u32 temp=0;
u16 ms = 0;
while(RTC_Wait_Synchro()); //等待同步
temp=RTC->TR;
*hour=RTC_BCD2DEC((temp>>16)&0X3F);
*min=RTC_BCD2DEC((temp>>8)&0X7F);
*sec=RTC_BCD2DEC(temp&0X7F);
ms=RTC->SSR;//获取亚秒
//根据公式计算精确到1ms的毫秒值
*msec = (0X3FF - ms)*1000/(0X3FF + 1);//1000在分子,防止值为0
*ampm=temp>>22;
temp=RTC->DR;//读一次日期,防止时间不更新
}
//BCD码转换为十进制数据
//val:要转换的BCD码
//返回值:十进制数据
u8 RTC_BCD2DEC(u8 val)
{
u8 temp=0;
temp=(val>>4)*10;
return (temp+(val&0X0F));
}
STM32F429寄存器版本的源码只精确到了秒,这里需要修改RTC_Init和RTC_Get_Time函数,使其精确到毫秒,其他的不变。
用法
项目中用来记录主控板(STM32)通过网络接收上位机下发文件的时间,文件发送请求时记录开始接收时间,文件发送完毕记录结束接收时间
tcpserver.c源文件
//获取开始接收时间
RTC_Get_Time(&hour,&min,&sec,&msec,&m);
printf("Start time:%02dh:%02dm:%02ds:%03dms\r\n",hour,min,sec,msec);
//获取接收结束时间
RTC_Get_Time(&hour,&min,&sec,&msec,&m);
printf("End time:%02dh:%02dm:%02ds:%03dms\r\n",hour,min,sec,msec);
串口输出如图
可以看到主控板接收上位机发送1M左右的bmp图片文件耗时2s多。
总结
**
1. 设置同步和异步分频系数精度,使得毫秒精确到1ms
2. 获取时分秒,读取TR寄存器并进行BCD转十进制转换
3. 获取日历,读取DR寄存器并进行BCD转十进制转换
4. 获取毫秒,读取SSR寄存器,根据公式转换
5. 最后获取一次日期,防止下次读取时间时不更新