BLE协议栈里有已经封装好的RTC时钟,时钟源可以是外部晶体振荡时钟也可以是内部RC时钟。
The32-kHzXOSC is designed to operate at32.768kHzand provide a stable clock signal for systems requiring time accuracy.The 32-kHz RCOS runs at32.753kHzwhen calibrated.
外部晶振更加精准一些!
主要的函数在OSAL_ClockBLE.c中;
void osalTimeUpdate( void ) { uint16 tmp; //为暂存变量,用于临时存放时间值 uint16 ticks625us; //用于存放timer2的溢出次数,每次溢出为625us,也就是说ticks625us代表了625us的个数 uint16 elapsedMSec = 0;//也是用来存放时间值的,只是它存放的值是上一次操作所保留下来的值,它最终存放的是时间的ms值 // Get the free-running count of 625us timer ticks tmp = ll_McuPrecisionCount();//这个函数就是用来读取timer2溢出次数的,溢出次数存放在T2MOVF2([23:16]),T2MOVF2([15:8]), T2MOVF0([7:0]), 一共有24bit if ( tmp != previousLLTimerTick )//判断时间是否有变化(正常情况下,随着程序的运行,tmp 这个值一直增大(16-bit)) { // Calculate the elapsed ticks of the free-running timer. ticks625us = tmp - previousLLTimerTick;//当前的时间值减去上一次的值,也就是代码再一次运行到这里所消耗的时间(注意单位为625us) // Store the LL Timer tick count for the next time through this function. previousLLTimerTick = tmp;//将当前值存储起来,为程序下一次运行到这里作准备 /* 下面红色部分的代码,都只是实现了一个功能,就是将ticks625us个625us 转换成 elapsedMSec 个ms(ms的整数部分)和remUsTicks 个us(ms的小数部分),“ *5 / 8” 等价于 “ *625 / 1000”(分子分母同时扩大40倍),同理“ *5 % 8” 等价于 “*625 % 1000” 至于MAXCALCTICKS ,程序中有一下两段注释,可以帮助我们理解 // (MAXCALCTICKS * 5) + (max remainder) must be <= (uint16 max), // so: (13105 * 5) + 7 <= 65535 #define MAXCALCTICKS ((uint16)(13105)) */ /* It is necessary to loop to convert the usecs to msecs in increments so as * not to overflow the 16-bit variables. */ while ( ticks625us > MAXCALCTICKS )//这个while是对溢出的操作 { ticks625us -= MAXCALCTICKS; elapsedMSec += MAXCALCTICKS * 5 / 8; remUsTicks += MAXCALCTICKS * 5 % 8; } // update converted number with remaining ticks from loop and the // accumulated remainder from loop tmp = (ticks625us * 5) + remUsTicks; // Convert the 625 us ticks into milliseconds and a remainder elapsedMSec += tmp / 8; remUsTicks = tmp % 8; // Update OSAL Clock and Timers if ( elapsedMSec )//判断时间是否到了1ms,如果等于或者超过1ms(elapsedMSec >= 1),则需要轮询任务列表 { osalClockUpdate( elapsedMSec );//更新osal操作系统的系统时间 osalTimerUpdate( elapsedMSec );//这个函数和任务的轮询调度有关,即和timeout有关 } } }
当然还有设置时间函数(UTCTime是从2000年1月1日00:00:00到至今的秒数)
/********************************************************************* * @fn osal_setClock * * @brief Set the new time. This will only set the seconds portion * of time and doesn't change the factional second counter. * * @param newTime - number of seconds since 0 hrs, 0 minutes, * 0 seconds, on the 1st of January 2000 UTC * * @return none */ void osal_setClock( UTCTime newTime ) { OSAL_timeSeconds = newTime; }
获得当前时间函数:
/********************************************************************* * @fn osal_getClock * * @brief Gets the current time. This will only return the seconds * portion of time and doesn't include the factional second * counter. * * @param none * * @return number of seconds since 0 hrs, 0 minutes, 0 seconds, * on the 1st of January 2000 UTC */ UTCTime osal_getClock( void ) { return ( OSAL_timeSeconds ); }
将秒数转换为年月日时分秒格式储存在结构体UTCTimeStruct(定义在OSAL_Clock.h)中
/********************************************************************* * @fn osal_ConvertUTCTime * * @brief Converts UTCTime to UTCTimeStruct * * @param tm - pointer to breakdown struct * * @param secTime - number of seconds since 0 hrs, 0 minutes, * 0 seconds, on the 1st of January 2000 UTC * * @return none */ void osal_ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime ) { // calculate the time less than a day - hours, minutes, seconds { uint32 day = secTime % DAY; tm->seconds = day % 60UL; tm->minutes = (day % 3600UL) / 60UL; tm->hour = day / 3600UL; } // Fill in the calendar - day, month, year { uint16 numDays = secTime / DAY; tm->year = BEGYEAR; while ( numDays >= YearLength( tm->year ) ) { numDays -= YearLength( tm->year ); tm->year++; } tm->month = 0; while ( numDays >= monthLength( IsLeapYear( tm->year ), tm->month ) ) { numDays -= monthLength( IsLeapYear( tm->year ), tm->month ); tm->month++; } tm->day = numDays; } }
校准时间时将年月日时分秒格式转换为秒的函数;
/********************************************************************* * @fn osal_ConvertUTCSecs * * @brief Converts a UTCTimeStruct to UTCTime * * @param tm - pointer to provided struct * * @return number of seconds since 00:00:00 on 01/01/2000 (UTC) */ UTCTime osal_ConvertUTCSecs( UTCTimeStruct *tm ) { uint32 seconds; /* Seconds for the partial day */ seconds = (((tm->hour * 60UL) + tm->minutes) * 60UL) + tm->seconds; /* Account for previous complete days */ { /* Start with complete days in current month */ uint16 days = tm->day; /* Next, complete months in current year */ { int8 month = tm->month; while ( --month >= 0 ) { days += monthLength( IsLeapYear( tm->year ), month ); } } /* Next, complete years before current year */ { uint16 year = tm->year; while ( --year >= BEGYEAR ) { days += YearLength( year ); } } /* Add total seconds before partial day */ seconds += (days * DAY); } return ( seconds ); }
example:
har tempbuf[10]={0}; UTCTimeStruct *Ti; osalTimeUpdate(); osal_ConvertUTCTime(Ti,osal_getClock()); tempbuf[0]=(Ti->hour)/10+'0'; tempbuf[1]=(Ti->hour)%10+'0'; tempbuf[2]=(Ti->minutes)/10+'0'; tempbuf[3]=(Ti->minutes)%10+'0'; tempbuf[4]=(Ti->seconds)/10+'0'; tempbuf[5]=(Ti->seconds)%10+'0'; Uart0Send_String(tempbuf,10);// 将时分秒在串口打印