RTL8762DK RTC(五)

概述

        本示例,只要介绍,RTC 如何实现 年/月/日 - 时/分/秒,又离成功进了一步 ^_^。

一、环境

1、硬件  (RTL8762DK + 128M Bits Falsh)

2、软件(keil IDE)

二、RTC的使用

1、创建examples_ble_rtc_clock工程,基于《examples_ble_led工程》来创建,创建步骤请参考第二篇文章。

2、新建rtc_clock文件夹,分别存放hub_clock.c与hub_clock.h这两个文件

2、打开examples_ble_rtc_clock工程

1)、hub_clock.h

#ifndef _WRISTBNAD_CLOCK_H_
#define _WRISTBNAD_CLOCK_H_


#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include "board.h"

#define IsLeapYear(yr) (!((yr) % 400) || (((yr) % 100) && !((yr) % 4)))

#define YearLength(yr) (IsLeapYear(yr) ? 366 : 365)


#define TIME_VALUE_HANDLER(v, max_v)			((v + max_v) % (max_v))
#define TIME_HOUR_HANDLER(hour)					TIME_VALUE_HANDLER(hour, 24)
#define TIME_MINUTES_HANDLER(minutes)			TIME_VALUE_HANDLER(minutes, 60)
#define TIME_SECONDS_HANDLER(seconds)			TIME_VALUE_HANDLER(seconds, 60)


#define BEGYEAR                     2000     // UTC started at 00:00:00 January 1, 2000
#define DAY                         86400UL  // 24 hours * 60 minutes * 60 seconds
#define SYSTEM_ORIGIN_DAY_OF_WEEK   (Sat)  //2000-01-01 is sat
#define LENGTH_OF_WEEK              (7)
#define RTC_CNT_MAX_VALUE           (1024*1024*16UL -1)         //RTC->CNT: [23:0]
#define RTC_PRESCALER_VALUE         0


extern uint32_t seconds_diff;
extern bool  seconds_cali_enable;

typedef enum
{
    MOn  = 0,
    Tues  = 1,
    Wed  = 2,
    Thur = 3,
    Fri  = 4,
    Sat  = 5,
    Sun  = 6
} DAY_OF_WEEK;

// To be used with
typedef struct
{
    volatile uint16_t year;    // 2000+
    volatile uint8_t month;    // 0-11
    volatile uint8_t day;      // 0-30
    volatile uint8_t seconds;  // 0-59
    volatile uint8_t minutes;  // 0-59
    volatile uint8_t hour;     // 0-23
	volatile DAY_OF_WEEK week;
} T_UTC_TIME;

/* time bit field */
typedef struct
{
    uint32_t seconds    :   6;
    uint32_t minute     :   6;
    uint32_t hours      :   5;
    uint32_t day        :   5;
    uint32_t month      :   4;
    uint32_t year       :   6;
}
time_bit_field_type_t;

typedef union
{
    uint32_t data;
    time_bit_field_type_t time;
} time_union_t;
/* time bit field */


typedef struct
{
    volatile uint16_t               current_stationary_time;
    volatile uint32_t               SecondCountRTC;
    volatile uint32_t               pre_rtc_tick_count;
    volatile T_UTC_TIME             Global_Time;
} __attribute__((packed)) SystemClock_t;

extern SystemClock_t SysClock;


#define ABS_PARAMS(a,b)             ((a>b) ? (a-b):(b-a))
typedef void (* pSystemClockCB)(void);
extern pSystemClockCB SystemClockCallBack;

void system_clock_init(uint32_t second);
void clock_driver_init(void);

DAY_OF_WEEK get_day_of_week(uint32_t secTime);//used to calculate day of week
void convert_to_utc_time(uint32_t sec_time);
uint32_t convert_time_to_second(time_union_t time);
void minute_system_clock_message_handle(void);
uint8_t get_system_clock_second(void);
uint16_t get_system_clock_millisecond(void);
time_union_t to_utc_time(uint32_t sec_time);

void set_sys_clock(time_union_t time);
bool get_system_work_state(void);


void clock_only_setting_date(uint16_t year, uint16_t month, uint16_t days);
void clock_only_setting_time(uint16_t hour, uint16_t minutes, uint16_t seconds);
uint32_t clock_get_timestamp(void);

#ifdef __cplusplus
}
#endif


#endif //_WRISTBNAD_CLOCK_H_

2)、hub_clock.c

/*********************************************************************************************************
*               Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
**********************************************************************************************************
* @file     wristband_clock.c
* @brief
* @details
* @author
* @date     2017-10-31
* @version  v0.1
*********************************************************************************************************
*/

#include "trace.h"
#include "string.h"
#include "ftl.h"
#include "app_task.h"
#include "rtl876x_rcc.h"
#include "rtl876x_rtc.h"
#include "rtl876x_nvic.h"
#include "hub_clock.h"
#include "otp.h"
#include "data_uart.h"


SystemClock_t SysClock __attribute__((aligned(4)));

#define     ClOCK_RTC_COMPARATOR        0
#define     RTC_CLOCK_SOURCE_FREQ       (OTP->bw_rf_low_clk_frac ? 32000:32768)


static uint32_t rtcTime = 2;		//1s interrupt

static void wall_clock_start(void);
static void update_system_clock(void);
static uint8_t month_length_calc(uint8_t lpyr, uint8_t mon);

pSystemClockCB SystemClockCallBack = NULL;


void clock_driver_init(void)
{
    system_clock_init(0);
}

/**
  * @brief   system clock init
  * @param   init offset secod, sometimes is zero
  * @return  void
  */
void system_clock_init(uint32_t second)
{
    RTC_DeInit();
    RTC_SetPrescaler(RTC_PRESCALER_VALUE);
    RTC_MaskINTConfig(RTC_INT_COMP0, ENABLE);
    RTC_INTConfig(RTC_INT_COMP0, DISABLE);

    /* Config RTC interrupt */
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 3;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    RTC_SystemWakeupConfig(ENABLE);
    convert_to_utc_time(second);
    /* Init ticks from RTC */
    SysClock.SecondCountRTC = second;       /* This should read from flash */
    SysClock.pre_rtc_tick_count = 0;
    wall_clock_start();
}
/**
  * @brief   RTC interrupt handler
  * @param   No parameter.
  * @return  void
  */
void RTC_Handler(void)
{
    uint32_t CompareValue = 0;
    data_uart_print("RTC->INT_SR = 0x%x, RTC->CR0 = 0x%x \r\n", RTC->INT_SR, RTC->CR0);
    if (RTC_GetINTStatus(RTC_INT_COMP0) == SET) {
      //   HUB_CLOCK_LOG("RTC_INT_CMP0");
        update_system_clock();
				
        CompareValue = RTC_GetCompValue(ClOCK_RTC_COMPARATOR) + (RTC_CLOCK_SOURCE_FREQ / (RTC_PRESCALER_VALUE + 1)) * rtcTime;

        RTC_SetCompValue(ClOCK_RTC_COMPARATOR, CompareValue & 0xFFFFFF);
        RTC_ClearCompINT(ClOCK_RTC_COMPARATOR);
    }
	
    if (RTC_GetINTStatus(RTC_INT_OVF) == SET) {
       //  HUB_CLOCK_LOG("RTC Overflow");
        RTC_ClearOverFlowINT();
    }
}

/**
  * @brief   minute system clock messafe handle
  * @param   void
  * @return  void
  */
void minute_system_clock_message_handle(void)
{
    /* get UTCTime time */
    convert_to_utc_time(SysClock.SecondCountRTC);

	#if 1
	data_uart_print("year:%d,month:%d,day:%d,hour:%d,minute:%d,second:%d\r\n",
                    SysClock.Global_Time.year,
                    SysClock.Global_Time.month, SysClock.Global_Time.day,
                    SysClock.Global_Time.hour, SysClock.Global_Time.minutes,
                    SysClock.Global_Time.seconds);
	#endif
    if (SystemClockCallBack != NULL) {
        SystemClockCallBack();
    }
	
		if ((SysClock.SecondCountRTC / 60) % 60 == 0) {

		}

    if (SysClock.Global_Time.year > 2000 && ((SysClock.Global_Time.hour >= 18) || (SysClock.Global_Time.hour < 10))) {
		
    } else {
		
    }
	
		if (SysClock.Global_Time.year > 2000 && SysClock.Global_Time.hour == 19 && SysClock.Global_Time.minutes == 0) {
			
		}
		
		if (SysClock.Global_Time.year > 2000 && SysClock.Global_Time.hour == 7 && SysClock.Global_Time.minutes == 0) {
			
		}
}

static uint8_t month_length_calc(uint8_t lpyr, uint8_t mon)
{
    uint8_t days = 31;

    if (mon == 1)   {
        days = (28 + lpyr); // feb
    } else {
		 // aug-dec
        if (mon > 6) {
            mon--;
        }

        if (mon & 1) {
            days = 30;
        }
    }
	
    return (days);
}

void convert_to_utc_time(uint32_t sec_time)
{
    /* calculate the time less than a day - hours, minutes, seconds */
    {
        uint32_t day = sec_time % DAY;
        SysClock.Global_Time.hour = day % 60UL;
				SysClock.Global_Time.minutes = day / 3600UL;
        SysClock.Global_Time.seconds = (day % 3600UL) / 60UL;
    }

    /* Fill in the calendar - day, month, year */
    {
        uint16_t numDays = sec_time / DAY;
        SysClock.Global_Time.year = BEGYEAR;
        while (numDays >= YearLength(SysClock.Global_Time.year)) {
            numDays -= YearLength(SysClock.Global_Time.year);
            SysClock.Global_Time.year++;
        }

        SysClock.Global_Time.month = 0;
        while (numDays >= month_length_calc(IsLeapYear(SysClock.Global_Time.year), SysClock.Global_Time.month)) {
            numDays -= month_length_calc(IsLeapYear(SysClock.Global_Time.year), SysClock.Global_Time.month);
            SysClock.Global_Time.month++;
        }

        SysClock.Global_Time.day = numDays;
        SysClock.Global_Time.month = SysClock.Global_Time.month + 1;
        SysClock.Global_Time.day = SysClock.Global_Time.day + 1;
    }
	
		SysClock.Global_Time.week = get_day_of_week(SysClock.SecondCountRTC); 
}

time_union_t to_utc_time(uint32_t sec_time)
{
	time_union_t union_time = {0};
	
    /* calculate the time less than a day - hours, minutes, seconds */
    {
        uint32_t day = sec_time % DAY;
        union_time.time.seconds = day % 60UL;
        union_time.time.minute = (day % 3600UL) / 60UL;
        union_time.time.hours = day / 3600UL;
    }

    /* Fill in the calendar - day, month, year */
    {
        uint16_t numDays = sec_time / DAY;
        union_time.time.year = 0;
        while (numDays >= YearLength(union_time.time.year)) {
            numDays -= YearLength(union_time.time.year);
            union_time.time.year++;
        }

        union_time.time.month = 0;
        while (numDays >= month_length_calc(IsLeapYear(union_time.time.year), union_time.time.month)) {
            numDays -= month_length_calc(IsLeapYear(union_time.time.year), union_time.time.month);
            union_time.time.month++;
        }

        union_time.time.day = numDays;
        union_time.time.month = union_time.time.month + 1;
        union_time.time.day = union_time.time.day + 1;
    }
	
		return union_time;
}

static void update_system_clock(void)
{
		data_uart_print("update_system_clock \r\n");
    SysClock.SecondCountRTC = SysClock.SecondCountRTC + (60 - SysClock.SecondCountRTC % 60);
    SysClock.pre_rtc_tick_count = RTC_GetCounter();

    T_IO_MSG clock_msg;
    clock_msg.type = IO_MSG_TYPE_CLOCK;
    app_send_msg_to_apptask(&clock_msg);
}

static void wall_clock_start(void)
{
    uint32_t CompareValue;
	
    data_uart_print("\r\n clock_start second_diff_value: %d\r\n", rtcTime);

    CompareValue = RTC_GetCounter() + (RTC_CLOCK_SOURCE_FREQ / (RTC_PRESCALER_VALUE + 1)) * rtcTime;
	
	  data_uart_print("CompareValue: %d\r\n", CompareValue);
	
    RTC_SetComp(ClOCK_RTC_COMPARATOR, CompareValue & 0xFFFFFF);
    RTC_MaskINTConfig(RTC_INT_COMP0, DISABLE);
    RTC_INTConfig(RTC_INT_COMP0, ENABLE);
    RTC_NvCmd(ENABLE);
    RTC_Cmd(ENABLE);
}

uint32_t convert_time_to_second(time_union_t time)
{
    uint32_t i = 0;
    uint32_t offset = 0;

    /* day time */
    offset += time.time.seconds;
    offset += time.time.minute * 60;
    offset += time.time.hours * 60 * 60;

    uint8_t leapYear = IsLeapYear(time.time.year + 2000);

    offset += DAY * (time.time.day - 1);

    for (i = 0; i < time.time.month - 1; ++i) {
        /* month start from 1 */
        offset += month_length_calc(leapYear, i) * DAY;
    }

    for (i = 0; i < time.time.year ; ++i) {
        if (IsLeapYear(i + 2000)) {
            offset += DAY * 366;
        } else {
            offset += DAY * 365;
        }
    }

    return offset;
}

void set_sys_clock(time_union_t time)
{
    SysC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ch_champion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值