基于GPS经纬度和当地时间计算日落日出时间实现

该代码实现了一个基于NRF52MCU平台的时间管理模块,包括UTC时间与本地时间的转换,以及日出、日落、中天、天亮和天黑时间的计算。主要函数有utc_to_local_time()和local_time_to_utc()进行时间转换,calc_sunrise_info()用于计算日出日落等相关时间。此外,还提供了logging功能以方便调试。
摘要由CSDN通过智能技术生成

以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 <math.h>
#include <stdio.h>
#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(ag<=-M_PI){
            ag=ag+2*M_PI;
        }
        else if(ag>M_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 <= -1){
            return -0.5;// 极昼
        }
        H0 = -acos(cosH0); // 升点时角(日出)若去掉负号 就是降点时角,也可以利用中天和升点计算
        H1 = -acos(cosH1);
        H = gst - lo - a; // 太阳时角
        s_sun_time.midDayTime = date - degree(H) / M_PI / 2 + tz; // 中天时间
        s_sun_time.dawnTime = date - degree(H - H1) / M_PI / 2 + tz;// 天亮时间
        return date - degree(H - H0) / M_PI / 2 + tz; // 日出时间,函数返回值
}

 

static void doubleToStr(double time,char *str)
{
       double t;
       int h,m,s;

        t = time + 0.5;
        t = (t - (int) t) * 24;
        h = (int) t;
        t = (t - h) * 60;
        m = (int) t;
        t = (t - m) * 60;
        s = (int) t;
        sprintf(str,"%02d:%02d:%02d",h,m,s);
}
 

//########################################################################################################################


/**
* @brieaf 计算日落,日出,中天,天亮,天黑时间
* @param[in] utc - 当前时间utc
* @param[in] lo -  经度
* @param[in] la - 纬度
* @param[in] zone - 时区
*/
 void calc_sunrise_info(uint32_t utc,double lo,double la,int32_t zone)
 {
	  rtc_time_t time;
	  
	  utc_to_local_time(utc,&time);
	  double jd = -lo/180*M_PI;
    double wd = la/180*M_PI;  
	  
	  double richu = timeToDouble(time.tm_year,time.tm_mon,time.tm_mday) - 2451544.5;
	 
	  for (uint32_t i = 0; i < 10; i++){
        richu = sunRiseTime(richu, jd, wd, zone/24.0);// 逐步逼近法算10次
    }
	 
		s_sun_time.sunrise_time = richu;
		s_sun_time.sunset_time = s_sun_time.midDayTime + s_sun_time.midDayTime - richu;
		s_sun_time.darkness_time = s_sun_time.midDayTime + s_sun_time.midDayTime-s_sun_time.dawnTime;
		
 }
 
 
 /**
 * @brieaf 获取日出时间
 */
 void get_sunrise_string(char *timestr)
 {
	 doubleToStr(s_sun_time.sunrise_time,timestr);
   NRF_LOG_INFO("------> sunrise %s",timestr);
 }
	 
 /**
 * @brieaf 获取日落时间
 */
 void get_sunset_string(char *timestr)
 {
	 doubleToStr(s_sun_time.sunset_time,timestr);
   NRF_LOG_INFO("------> sunset_time %s",timestr);
 }
 
 /**
 * @brieaf 获取中天时间
 */
 void get_midDayTime_string(char *timestr)
 {
	 doubleToStr(s_sun_time.midDayTime,timestr);
   NRF_LOG_INFO("------> midDayTime %s",timestr);
 }
 
 
 /**
 * @brieaf 获取天亮时间
 */
 void get_dawnTime_string(char *timestr)
 {
	 doubleToStr(s_sun_time.dawnTime,timestr);
   NRF_LOG_INFO("------> dawnTime %s",timestr);
 }
 
 /**
 * @brieaf 获取天黑时间
 */
 void get_darkness_time_string(char *timestr)
 {
	 doubleToStr(s_sun_time.darkness_time,timestr);
   NRF_LOG_INFO("------> darkness_time %s",timestr);
 }
 

调用calc_sunrise_info函数计算

calc_sunrise_info(1633750052,113.9167f,22.6446,8);
  • 调用获取结果函数
  char buf[40];
  get_sunrise_string(buf);
  get_sunset_string(buf);
  get_midDayTime_string(buf);
  get_dawnTime_string(buf);
  get_darkness_time_string(buf);
  • 运行结果
    <00> info> sunrise_calc: ------> sunrise 06:18:30
    00>
    <00> info> sunrise_calc: ------> sunset_time 18:04:52
    00>
    <00> info> sunrise_calc: ------> midDayTime 12:11:41
    00>
    <00> info> sunrise_calc: ------> dawnTime 05:56:01
    00>
    <00> info> sunrise_calc: ------> darkness_time 18:27:22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风雨依依

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

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

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

打赏作者

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

抵扣说明:

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

余额充值