1.目的
nrf51822用定时器模拟一个万年历
2.分析
3.平台:
协议栈版本:SDK10.0.0
编译软件:keil 5.14
硬件平台:nrf51822最小系统
例子:SDK 10.0.0\examples\ble_peripheral\ble_app_uart\pca10028\s110\arm4
4.步骤上传图片
/******************************************************************************** * @file calender.c * @author Depth * @version V1.0.0 * @date 12-May-2014 * @Emial [email protected] * @brief calender module based on app timer ******************************************************************************/ #include "calender.h" /********************************************************************* * MACROS */ #define YearLength(yr) (IsLeapYear(yr) ? 366 : 365) //日历变量 UTCTimeStruct Time_iOS = {8,59,15,9,6,2015}; UTCTimeStruct Time_Current; /********************************************************************* * CONSTANTS */ // (MAXCALCTICKS * 5) + (max remainder) must be <= (uint16_t max), // so: (13105 * 5) + 7 <= 65535 #define MAXCALCTICKS ((uint16_t)(13105)) #define BEGYEAR 1970 // UTC started at 00:00:00 January 1, 2000 #define DAY 86400UL // 24 hours * 60 minutes * 60 seconds /********************************************************************* * EXTERNAL FUNCTIONS */ extern uint16_t ll_McuPrecisionCount(void); /********************************************************************* * LOCAL VARIABLES */ //static uint16_t previousLLTimerTick = 0; //static uint16_t remUsTicks = 0; //static uint16_t timeMSec = 0; // number of seconds since 2010.1.1. 00:00:00 UTCTime TimeSeconds = 0; /********************************************************************* * LOCAL FUNCTION PROTOTYPES */ static uint8_t monthLength( uint8_t lpyr, uint8_t mon ); /********************************************************************* * FUNCTIONS */ /********************************************************************* * @fn Set_Clock * * @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 Set_Clock( UTCTime newTime ) { TimeSeconds = newTime; } /********************************************************************* * @fn Get_Clock * * @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 Get_Clock( void ) { return ( TimeSeconds ); } /********************************************************************* * @fn 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 */ uint16_t numDays =0; void ConvertUTCTime( UTCTimeStruct *tm, UTCTime secTime ) { // calculate the time less than a day - hours, minutes, seconds { uint32_t day = secTime % DAY; // 求出最后一天的剩余秒数,(除去整数的天数之后的剩余秒数) tm->seconds = day % 60UL; // 求出最后一分钟的剩余秒数 (最后一天的剩余秒数对60求余) tm->minutes = (day % 3600UL) / 60UL; //求出 最后一小时剩余的整分钟数 tm->hour = day / 3600UL; //求最后一天的整小时数 } // Fill in the calendar - day, month, year { 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->month++; tm->day = numDays; tm->day++; } } /********************************************************************* * @fn monthLength * * @param lpyr - 1 for leap year, 0 if not * * @param mon - 0 - 11 (jan - dec) * * @return number of days in specified month */ static uint8_t monthLength( uint8_t lpyr, uint8_t mon ) { uint8_t days = 31; if ( mon == 1 ) // feb { days = ( 28 + lpyr ); } else { if ( mon > 6 ) // aug-dec { mon--; } if ( mon & 1 ) { days = 30; } } return ( days ); } /********************************************************************* * @fn 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 ConvertUTCSecs( UTCTimeStruct *tm ) { uint32_t 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_t days = tm->day; /* Next, complete months in current year */ { int8_t month = tm->month - 1;// while ( --month >= 0 ) { days += monthLength( IsLeapYear( tm->year ), month ); } } /* Next, complete years before current year */ { uint16_t year = tm->year; while ( --year >= BEGYEAR ) { days += YearLength( year ); } } /* Add total seconds before partial day */ seconds += (days * DAY); } return ( seconds ); } /********************************************************************* * @fn CaculateWeekday * * @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) */ uint8_t CaculateWeekday(UTCTimeStruct *ptime) { // ¸ù¾ÝÈÕÆÚÊý¼ÆËãÐÇÆÚÊý uint16_t year = ptime->year ; uint8_t mounth = ptime->month; uint8_t day = ptime->day + 1; uint8_t week; if(mounth==1 || mounth==2) { mounth += 12; year--; } week = (day + 2*mounth + 3*(mounth+1)/5 + year + year/4 - year/100 + year/400)%7; if(week == 0) week = 7; return (uint8_t)week; }
#include "nrf51.h" #include "nrf_gpio.h" #include "rtc.h" #include "app_scheduler.h" #include "ble_gatts.h" #include "app_error.h" #include "nrf_gpio.h" //#include "power_manger.h" #include <stdbool.h> #include "calender.h" #include "app_timer.h" #include <stdint.h> #include <string.h> #include "nordic_common.h" #include "nrf.h" #include "nrf_gpio.h" #include "nrf51_bitfields.h" #include "app_error.h" #include "calender.h" /********************************************************** 注册一个1s的时间用于RTC ********************************************************/ #define APP_TIMER_PRESCALER 0 //wall clock id app_timer_id_t SecondID; //广播的时候闪烁蓝灯 #define ONESECOND_INTERVAL APP_TIMER_TICKS(1000, APP_TIMER_PRESCALER) // 广播时间设置 static void SECONED_ADD_clock(void * p_context) //采集皮肤数据灯闪烁指示 { (void)p_context; UTCTimeStruct utc; TimeSeconds++ ; //一天有86400s 一个小时 3600s ConvertUTCTime( &utc, Get_Clock() ); // ?????? if(utc.minutes == 0 && utc.seconds == 0 && utc.year !=0) { //每个小时 if(utc.hour == 0) { //每一天 if(utc.day == 0) { //每一个月 } } } } /************************************************************************** * system clock init ***************************************************************************/ void SECOND_clock_init(void) { uint32_t err_code; UTCTimeStruct utc; utc.seconds = 0x00; utc.minutes = 0x00; utc.hour = 0x00; utc.day = 0x00; //CC2540 ???? 0 -30 utc.month = 0x00; //CC2540 ???? 0 -11 utc.year = 2000; Set_Clock( ConvertUTCSecs( &utc ) ); err_code = app_timer_create(&SecondID, APP_TIMER_MODE_REPEATED, SECONED_ADD_clock); //广播事件 APP_ERROR_CHECK(err_code); err_code = app_timer_start(SecondID, ONESECOND_INTERVAL, NULL); APP_ERROR_CHECK(err_code); }
SECOND_clock_init();//初始化后,系统每1s,TimeSeconds加一
ConvertUTCTime( &utc, Get_Clock() ); // 获取当前时间
CaculateWeekday(); //可以获得当前的星期几