以NRF52 MCU平台实现,先实现UTC及要本时间等转换函数
#ifndef __RTC_MODULE_H__
#define __RTC_MODULE_H__
#include "time.h"
#include "stdbool.h"
#include "stdint.h"
#include "sdk_config.h"
#include "nrf_atomic.h"
#pragma anon_unions
#ifdef __cplusplus
extern "C" {
#endif
#define INIT_UTC (1609502400)
#define ONE_DAY_UTC 86400
typedef struct{
int tm_sec; /* seconds after the minute, 0 to 60
(0 - 60 allows for the occasional leap second) */
int tm_min; /* minutes after the hour, 0 to 59 */
int tm_hour; /* hours since midnight, 0 to 23 */
int tm_mday; /* day of the month, 1 to 31 */
int tm_mon; /* months since January, 0 to 11 */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday, 0 to 6 */
int tm_yday; /* days since January 1, 0 to 365 */
int tm_isdst; /* Daylight Savings Time flag */
union { /* ABI-required extra fields, in a variety of types */
struct {
int __extra_1, __extra_2;
};
struct {
long __extra_1_long, __extra_2_long;
};
struct {
char *__extra_1_cptr, *__extra_2_cptr;
};
struct {
void *__extra_1_vptr, *__extra_2_vptr;
};
};
}rtc_time_t;
extern int8_t time_zone;
extern uint8_t g_sync_utc_flag;
uint32_t utc_inc_one(void);
uint32_t rtcm_get_sys_utc(void);
void rtcm_set_sys_utc(uint32_t tmp_utc);
void rtcm_read_sys_time(rtc_time_t *tmp_rtc);
void rtcm_secs_to_date_time(uint32_t t, rtc_time_t *p_time);
void utc_to_local_time(uint32_t utc,rtc_time_t *pTime);
void local_time_to_utc(uint32_t *utc,rtc_time_t *pTime);
#ifdef __cplusplus
}
#endif
#endif
#include "rtc_module.h"
#include "main.h"
#include "nrfx.h"
/***********************************************************************
* macro define
************************************************************************
*/
#define NRF_LOG_MODULE_NAME rtc_module
#if ANT_HRM_LOG_ENABLED
#define NRF_LOG_LEVEL 3
#define NRF_LOG_INFO_COLOR 3
#else // ANT_HRM_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // ANT_HRM_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
uint8_t g_sync_utc_flag;
int8_t time_zone = 8; // 时区
static nrf_atomic_u32_t sys_utc = INIT_UTC;
/*************************************************************************
** function name: rtcm_get_sys_utc
** description: get the system utc
** input para:
**
** return: return the system utc
**************************************************************************/
uint32_t rtcm_get_sys_utc(void)
{
uint32_t utc = nrf_atomic_u32_fetch_or(&sys_utc,0);
return utc;
}
/**
* @brieaf utc原子操作加1
*/
uint32_t utc_inc_one(void)
{
return nrf_atomic_u32_add(&sys_utc,1);
}
/*************************************************************************
** function name: rtcm_set_sys_utc
** description: set the system utc
** input para:
**
** return:
**************************************************************************/
void rtcm_set_sys_utc(uint32_t tmp_utc)
{
uint32_t utc = nrf_atomic_u32_store(&sys_utc,tmp_utc);
NRF_LOG_INFO("=========Set_time=%d",sys_utc);
}
/*************************************************************************
** function name: rtcm_read_sys_time
** description: read the system rtc
** input para: tmp_rtc--the rtc you want to read
**
** return:
**************************************************************************/
void rtcm_read_sys_time(rtc_time_t *tmp_rtc)
{
//rtc_secs_to_date_time(sys_utc+(u32_t)8*3600, tmp_rtc);
uint32_t utc = nrf_atomic_u32_fetch_or(&sys_utc,0);
utc_to_local_time(utc, tmp_rtc);
}
/**
* @brieaf 本地时间转UTC
*/
void local_time_to_utc(uint32_t *utc,rtc_time_t *pTime)
{
struct tm p;
memcpy(&p,pTime,sizeof(struct tm));
p.tm_year -= 1900;
p.tm_mon -= 1;
*utc =mktime(&p);
}
/**
* @brieaf utc转本地时间
*/
void utc_to_local_time(uint32_t utc,rtc_time_t *pTime)
{
struct tm *p;
p = localtime(&utc);
p->tm_year += 1900;
p->tm_mon++;
memcpy(pTime,p,sizeof(struct tm));
}
计算日出日落相关函数
#ifndef __BSP_SUNRISE_CALC_H
#define __BSP_SUNRISE_CALC_H
#include
#include
#include "rtc_module.h"
#define M_PI 3.1415926
#ifdef __cplusplus
extern "C" {
#endif
typedef struct TAG_SUNRISE
{
double sunrise_time; // 日出
double sunset_time; // 日落
double midDayTime; //中天时间
double dawnTime; //天亮时间
double darkness_time; //天黑时间
}SUNRISE_TIME_T;
void calc_sunrise_info(uint32_t utc,double lo,double la,int32_t zone);
/**
* @brieaf 获取日出时间
*/
void get_sunrise_string(char *timestr);
/**
* @brieaf 获取日落时间
*/
void get_sunset_string(char *timestr);
/**
* @brieaf 获取中天时间
*/
void get_midDayTime_string(char *timestr);
/**
* @brieaf 获取天亮时间
*/
void get_dawnTime_string(char *timestr);
/**
* @brieaf 获取天黑时间
*/
void get_darkness_time_string(char *timestr);
#ifdef __cplusplus
}
#endif
#endif
#include "BSP_sunrise_calc.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#define NRF_LOG_MODULE_NAME sunrise_calc
#define NRF_LOG_LEVEL 3
#define NRF_LOG_INFO_COLOR 4
#define NRF_LOG_DEBUG_COLOR 3
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
static double RAD = 180.0 * 3600 /M_PI;
static SUNRISE_TIME_T s_sun_time;
/*************************
* 儒略日的计算
*
* @param y 年
*
* @param M 月
*
* @param d 日
*
* @param h 小时
*
* @param m 分
*
* @param s秒
*
* @return int
***************************/
static double timeToDouble(int y, int M, double d)
{
// double A=0;
double B=0;
double jd=0;
//设Y为给定年份,M为月份,D为该月日期(可以带小数)。
//若M > 2,Y和M不变,若 M =1或2,以Y–1代Y,以M+12代M,换句话说,如果日期在1月或2月,则被看作是在前一年的13月或14月。
//对格里高利历有 :A = INT(Y/100) B = 2 - A + INT(A/4)
//对儒略历,取 B = 0
//JD = INT(365.25(Y+4716))+INT(30.6001(M+1))+D+B-1524.5 (7.1)
B=-13;
jd=floor(365.25 * (y + 4716))+ floor(30.60001 * (M + 1)) +B+ d- 1524.5;
return jd;
}
/****************************
* @param t 儒略世纪数
*
* @return 太阳黄经
*****************************/
static double sunHJ(double t)
{
double j;
t = t + (32.0 * (t + 1.8) * (t + 1.8) - 20) / 86400.0 / 36525.0;
// 儒略世纪年数,力学时
j = 48950621.66 + 6283319653.318 * t + 53 * t * t - 994 + 334166 *cos(4.669257 + 628.307585 * t) + 3489 * cos(4.6261 + 1256.61517 * t) + 2060.6 * cos(2.67823 + 628.307585 * t) * t;
return (j / 10000000);
}
static double mod(double num1, double num2)
{
num2 = fabs(num2);
// 只是取决于Num1的符号
return num1 >= 0 ?(num1 - (floor(num1 / num2)) * num2 ): ((floor(fabs(num1) / num2)) * num2 - fabs(num1));
}
/********************************
* 保证角度∈(-π,π)
*
* @param ag
* @return ag
***********************************/
static double degree(double ag)
{
ag = mod(ag, 2 * M_PI);
if(agM_PI){
ag=ag-2*M_PI;
}
return ag;
}
/***********************************
*
* @param date 儒略日平午
*
* @param lo 地理经度
*
* @param la 地理纬度
*
* @param tz 时区
*
* @return 太阳升起时间
*************************************/
static double sunRiseTime(double date, double lo, double la, double tz)
{
double t,j,sinJ,cosJ,gst,E,a,D,cosH0,cosH1,H0,H1,H;
date = date - tz;
// 太阳黄经以及它的正余弦值
t = date / 36525;
j = sunHJ(t);
// 太阳黄经以及它的正余弦值
sinJ = sin(j);
cosJ = cos(j);
// 其中2*M_PI*(0.7790572732640 + 1.00273781191135448*jd)恒星时(子午圈位置)
gst = 2 * M_PI * (0.779057273264 + 1.00273781191135 * date) + (0.014506 + 4612.15739966 * t + 1.39667721 * t * t) / RAD;
E = (84381.406 - 46.836769 * t) / RAD; // 黄赤交角
a = atan2(sinJ * cos(E), cosJ);// '太阳赤经
D = asin(sin(E) * sinJ); // 太阳赤纬
cosH0 = (sin(-50 * 60 / RAD) - sin(la) * sin(D)) / (cos(la) * cos(D)); // 日出的时角计算,地平线下50分
cosH1 = (sin(-6 * 3600 / RAD) - sin(la) * sin(D)) / (cos(la) * cos(D)); // 天亮的时角计算,地平线下6度,若为航海请改为地平线下12度
// 严格应当区分极昼极夜,本程序不算
if (cosH0 >= 1 || cosH0 sunrise_calc: ------> sunrise 06:18:30 00> info> sunrise_calc: ------> sunset_time 18:04:52 00> info> sunrise_calc: ------> midDayTime 12:11:41 00> info> sunrise_calc: ------> dawnTime 05:56:01 00> info> sunrise_calc: ------> darkness_time 18:27:22