太阳高度角与方位角计算程序-stm32G070-ESP32 arduino- python(下)

按照UTC时间和经度、维度计算太阳高度度角、方位角等信息。

 

复制代码
/*
#纬度   latitude   北半球正          -90  ~  90度
#经度   altitude   东半球正          -180 ~ 180度
#太阳真时    apparent_solar_time
#太阳时角    solar_hour_angle        -180~180度
#计算赤纬角  solar_declination_angle -23.45 ~ 23.45度
#计算高度角  solar_altitude_angle    -90~90度
#太阳方位角  solar_azimuth_angle     -180~ 180度
#太阳天顶角  solar_zenith_angle       0 -180度
#太阳升起时角solar_hour_angle_sunrise  -180~0度
*/
#ifndef __solar_position_algorithm_header
#define __solar_position_algorithm_header
#include "stm32g0xx_hal.h"
typedef struct
{
    //----------------------INPUT VALUES------------------------
    int16_t year;           //UTC输入: 4-digit year,    valid range: 0 to 6000, error code: 1
    int16_t month;          //UTC输入: 2-digit month,         valid range: 1 to 12, error code: 2
    int16_t day;            //UTC输入: 2-digit day,           valid range: 1 to 31, error code: 3
    int16_t hour;           //UTC输入: Observer local hour,   valid range: 0 to 24, error code: 4
    int16_t minute;         //UTC输入: Observer local minute, valid range: 0 to 59, error code: 5
    int16_t second;         //UTC输入: Observer local second, valid range: 0 to 59, error code: 6
    int16_t timezone;     //输入: 当地Observer time zone (negative west of Greenwich)
                          //       valid range: -18   to   18 hours,   error code: 7

    float longitude;    // 输入:当地经度Observer longitude (negative west of Greenwich)
                        //           valid range: -180  to  180 degrees, error code: 8

    float latitude;     // 输入:当地纬度Observer latitude (negative south of equator)
                        //           valid range: -90   to   90 degrees, error code: 9
    //---------------------OUTPUT VALUES------------------------
      int16_t  ndays;                  //UTC时间,从元旦(含)计,全年第几天
    
      float  mean_solar_time;         //输出:当地平太阳时, 由hhmmss计算,单位 分钟
      float  error_time;              //时差:当地真太阳时与平太阳时之差,单位 分钟
    float  apparent_solar_time;     //输出:当地太阳真时    0-24,单位 分钟
      float  solar_hour_angle;        //输出:当地太阳时角    -180~180度
      float  solar_declination_angle; //输出:当地赤纬角      -23.45 ~ 23.45度
      float  solar_altitude_angle;    //输出:当地太阳高度角  -90~90度
        float  solar_azimuth_angle;     //输出:当地太阳方位角  -180~ 180度
        float  solar_hour_angle_sunrise;//输出:当地升起时刻的太阳时角-180~0度
} spa_data;

//Calculate SPA output values (in structure) based on input values passed in structure
uint8_t sunpos_cal(spa_data *spa);
// 根据日期算天数
uint8_t date2days_cal(spa_data *spa);
// 根据天数算日期
uint8_t days2date_cal(spa_data *spa);
// 输入和输出数据打印
void sunpos_print(spa_data *spa);
#endif
复制代码

 

 

 

复制代码
#include <timeformat.h>
#include <sunPosition.h>
#include <math.h>
#define PI         3.14159265f

#include <rtthread.h> /* 打印结果使用 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h> //字符串和数值间转换
//正数范围(3.402823466e+38F)
//负数范围(1.175494351e-38F)
// double的范围
//正数范围(1.7976931348623158e+308)
//负数范围(2.2250738585072014e-308)

// 计算 平太阳时
// INPUT:  
//         Beijing_time       北京标准时间,    单位:分钟
//                 longitude_beijing  北京标准时间经度,单位:度
//                 longitude_location 当地时间经度,东半球正,单位:度
//                 latitude_locaiton  当地时间维度,北半球正,单位:度
// OUTPUT: 时差,单位:分钟
float mean_solar_time_cal(float Beijing_time,float longitude_beijing,float  longitude_location,float latitude_locaiton)
{/*计算设备所在地的平太阳时*/
    float mean_solar_time;
    if(latitude_locaiton>=0)
    {
     mean_solar_time = Beijing_time - 4*(longitude_beijing-longitude_location);
    }
    else
    {
     mean_solar_time = Beijing_time + 4*(longitude_beijing-longitude_location);
    }
    return mean_solar_time;
}
// 不用北京时间,直接由UTC时间hhmmss计算当地平太阳时
// INPUT:  
//         utc_minutes       UTC标准时间,由当天的hhmmss计算得到 单位:分钟
//                 longitude_location 当地时间经度,东半球正,单位:度
// OUTPUT: 当地平太阳时,单位:分钟
float local_mean_solar_time_cal(float utc_minutes,float  longitude_location)
{/*计算设备所在地的平太阳时*/
    float mean_solar_time;
    if(longitude_location>=0)
    {
     mean_solar_time = utc_minutes - 4*(0-longitude_location);
    }
    else
    {
     mean_solar_time = utc_minutes + 4*(0-longitude_location);
    }
    return mean_solar_time;
}
// 计算   平太阳时+ET=真太阳
// INPUT: 当年第几天,从元旦计,1~365
// OUTPUT: 时差,单位:分钟
float time_error(double nday)
{/*计算设备所在地的平太阳时*/
    float gama_big;
    float ET;
    gama_big = 2*PI*(nday-1)/365;
    ET = 0.01719f+0.428145f*cos(gama_big);
    ET=ET-7.3520484f*sin(gama_big);
    ET=ET-3.349758f*cos(gama_big*2);
    ET=ET-9.371988f*sin(gama_big*2);
    return ET;
}
// FUN:    计算真太阳时 单位:分钟
// INPUT: 
//         mean_solar_time 单位:分钟
//         error_time      单位:分钟
// OUTPUT: apparent_solar_time 单位:分钟
float apparent_solar_time_cal(const float mean_solar_time,const float error_time)
{/*计算设备所在地的真太阳时*/
    float apparent_solar_time;
    apparent_solar_time = mean_solar_time + error_time;
    return apparent_solar_time;
}

// FUN:    计算真太阳时 单位:分钟
// INPUT: 
//         mean_solar_time 单位:分钟
//         error_time      单位:分钟
// OUTPUT: apparent_solar_time 单位:分钟

float solar_hour_angle_cal(float apparent_solar_time)
{/*计算设备所在地的时间角度*/
    float temp;
    temp = (apparent_solar_time-12*60)*15.00f/60;
    return temp;
}

// FUN:   计算当天赤纬角度
// INPUT: nday  当年第几天,从元旦计,1~365
// OUTPUT: solar_declination_angle,单位:度
float solar_declination_angle_cal(float nday)
{/*计算当天赤纬角度*/
    double solar_declination_angle;
    solar_declination_angle = 23.45f *sin(2*PI*(284+nday)/365);
    return solar_declination_angle;
}

// FUN:   计算当天日升高度角度
// INPUT: 
//       latitude                纬度     度
//       solar_declination_angle 赤纬角   度
// OUTPUT: solar_declination_angle,单位:度
float solar_hour_angle_sunrise_cal(float latitude, float solar_declination_angle)
{/*计算计算当天日升高度角度*/
    float  solar_hour_angle_sunrise;
    /*计算余弦值*/
    solar_hour_angle_sunrise = sin(PI*latitude/180)*sin(PI*solar_declination_angle/180);
    solar_hour_angle_sunrise = solar_hour_angle_sunrise/( cos(PI*latitude/180)*cos(PI*solar_declination_angle/180) );
    if(solar_hour_angle_sunrise>1)//#截断误差处理
            solar_hour_angle_sunrise=1;
    if(solar_hour_angle_sunrise<-1)//#截断误差处理
            solar_hour_angle_sunrise=-1;    
    /*计算角度值*/    
    solar_hour_angle_sunrise = (-acos(-solar_hour_angle_sunrise)*180/PI);
    return solar_hour_angle_sunrise;
}

// FUN:   计算太阳高度角度
// INPUT: 
//        latitude                 当地纬度,   单位:度
//        solar_declination_angle  当天赤纬角, 单位:度
//        solar_hour_angle         当地太阳时角, 单位:度
// OUTPUT: solar_declination_angle,单位:度
float solar_altitude_angle_cal(float latitude,float solar_declination_angle,float solar_hour_angle)
{/*计算太阳高度角度*/
    float item1,item2;
    float total;
    float solar_altitude_angle;
    item1=sin(PI*latitude/180)*sin(PI*solar_declination_angle/180);
  item2=cos(PI*latitude/180)*cos(PI*solar_declination_angle/180)*cos(PI*solar_hour_angle/180);    
    total = item1+item2;
    if(total<-1)//#截断误差处理
            total=-1;
    if(total>1)//#截断误差处理
            total=1;
    solar_altitude_angle=asin(total)*180/PI;
    return solar_altitude_angle;
}

// FUN:   计算太阳方位角度
// INPUT: 
//        latitude                 当地纬度,   单位:度
//        solar_declination_angle  当天赤纬角, 单位:度
//        solar_hour_angle         当地太阳时角,   单位:度
//    solar_altitude_angle     当地太阳高度角, 单位:度
// OUTPUT: solar_declination_angle,单位:度
float solar_azimuth_angle_cal(float latitude,float solar_declination_angle,float solar_hour_angle,float solar_altitude_angle)
{/*计算太阳方位角度*/
  float sin_azimuth;
    float cos_azimuth;
    float azimuth;
    sin_azimuth = cos(solar_declination_angle*PI/180);
  sin_azimuth = sin_azimuth*sin(solar_hour_angle*PI/180);
    sin_azimuth = sin_azimuth/cos(solar_altitude_angle*PI/180);
    
    cos_azimuth =  sin(solar_altitude_angle*PI/180);
  cos_azimuth =  cos_azimuth*sin(latitude*PI/180);
  cos_azimuth =  cos_azimuth-sin(solar_declination_angle*PI/180);    
    cos_azimuth =  cos_azimuth /cos(solar_altitude_angle*PI/180);
    cos_azimuth =  cos_azimuth/cos(latitude*PI/180);

    if(cos_azimuth>1)
            cos_azimuth=1;
    if(cos_azimuth<-1)
            cos_azimuth=-1;
    if(sin_azimuth<=0)
            azimuth=-acos(cos_azimuth )*180/PI;
    if(sin_azimuth>0)
            azimuth= acos(cos_azimuth )*180/PI;     
    return azimuth;
}
// 输入合法性检查
uint8_t validate_inputs(spa_data *spa)
{
    if ((spa->year        < -2000) || (spa->year        > 6000)) return 1;
    if ((spa->month       < 1    ) || (spa->month       > 12  )) return 2;
    if ((spa->day         < 1    ) || (spa->day         > 31  )) return 3;
    if ((spa->hour        < 0    ) || (spa->hour        > 24  )) return 4;
    if ((spa->minute      < 0    ) || (spa->minute      > 59  )) return 5;
    if ((spa->second      < 0    ) || (spa->second      > 59  )) return 6;
    if ((spa->hour        == 24  ) && (spa->minute      > 0   )) return 5;
    if ((spa->hour        == 24  ) && (spa->second      > 0   )) return 6;

    if (( spa->timezone    > 18  ) || (spa->timezone   <- 18) ) return 8;
    if (( spa->longitude   > 180 ) || (spa->longitude  <- 180)) return 9;
    if (( spa->latitude    > 180 ) || (spa->latitude   <- 180)) return 10;    
    
    return 0;
}

// 根据日期,算天数
uint8_t date2days_cal(spa_data *spa)
{
    const uint8_t Leap_Year_month_days[]    ={31,29,31,30,31,30,31,31,30,31,30,31};
    const uint8_t Ordinary_Year_month_days[]={31,28,31,30,31,30,31,31,30,31,30,31};     
    uint8_t  Is_Leap_Year;     
    uint16_t index;   
    uint16_t ndays;
     /*计算从元旦计,天数*/
     Is_Leap_Year=IsLeapYear(spa->year);//判断是否为闰年 
    
     ndays =0;
   for(index=1;index< spa->month;index++)
     {
         if(Is_Leap_Year==1)
             ndays= ndays + Leap_Year_month_days[index-1];
         else
             ndays= ndays + Ordinary_Year_month_days[index-1];             
     }    
   spa->ndays=ndays;
     return 0;       
}

// 根据天数算日期
uint8_t days2date_cal(spa_data *spa)
{
    const uint8_t Leap_Year_month_days[]    ={31,29,31,30,31,30,31,31,30,31,30,31};
    const uint8_t Ordinary_Year_month_days[]={31,28,31,30,31,30,31,31,30,31,30,31};
    
    uint8_t  Is_Leap_Year;     
    uint16_t index;   
    uint16_t ndays;
     /*计算从元旦计,天数*/
     Is_Leap_Year=IsLeapYear(spa->year);//判断是否为闰年
     ndays=0;
   for(index=1;index<= 12;index++)
     {
         if(Is_Leap_Year==1)
         {    
             if((ndays< spa->ndays)&&(spa->ndays <= ndays + Leap_Year_month_days[index-1]))
             {
                 spa->month = index;            
           spa->day =     spa->ndays-ndays;        
           break;                 
             }
             ndays = ndays+ Leap_Year_month_days[index-1];
         }
         else
         {
             if((ndays< spa->ndays)&&(spa->ndays <= ndays + Ordinary_Year_month_days[index-1]))
             {
                 spa->month = index;            
           spa->day =     spa->ndays-ndays;        
           break;                 
             }         
             ndays= ndays + Ordinary_Year_month_days[index-1];    
         }             
     }    
     return 0;
}
// 计算Sun Position
// 2023-4-3日: 修改,由UTC计算太阳平时
uint8_t sunpos_cal(spa_data *spa)
{
     uint8_t ret;     
     int16_t local_ndays;
     float utc_minutes;
     ret =0;
     ret= validate_inputs(spa);
     if(ret!=0) return ret;

     /*由UTC时间计算当地当天平太阳时*/    
     utc_minutes = spa->hour*60+spa->minute + spa->second/60.0f;
    
     utc_minutes= local_mean_solar_time_cal(utc_minutes,spa->longitude);
    
     if(utc_minutes>1440)// 24h* 60m,day不同
     {
         utc_minutes=utc_minutes-1440;
         local_ndays=spa->ndays +1;
         local_ndays = local_ndays %(365+1);
     }
     if(utc_minutes<0)   // 24h* 60m,day不同
     {
         utc_minutes=utc_minutes+1440;// 24h* 60m
         local_ndays=spa->ndays +354;        // 周期内 减1 
         local_ndays = local_ndays %(365+1);
     }     
     spa->mean_solar_time = utc_minutes;
     
     /*计算当天当地时差(真太阳时-平太阳时)*/
   spa->error_time =     time_error(local_ndays); 
     /*计算当天当地真太阳时*/    
   spa->apparent_solar_time =apparent_solar_time_cal(spa->mean_solar_time,spa->error_time);
     /*计算当天当地太阳时角*/
   spa->solar_hour_angle =     solar_hour_angle_cal(spa->apparent_solar_time);
     /*计算当天当地赤纬角*/    
     spa->solar_declination_angle=solar_declination_angle_cal(local_ndays);
     /*计算当时当地高度角*/         
   spa->solar_altitude_angle = solar_altitude_angle_cal(spa->latitude,spa->solar_declination_angle,spa->solar_hour_angle); 
     /*计算当时当地方位角*/        
   spa->solar_azimuth_angle =solar_azimuth_angle_cal(spa->latitude,spa->solar_declination_angle,spa->solar_hour_angle,spa->solar_altitude_angle);
     /*计算当天当地日升角*/     
     spa->solar_hour_angle_sunrise =  solar_hour_angle_sunrise_cal(spa->latitude, spa->solar_declination_angle);     
     return 0;
}
// 打印结果
// 2023-4-3日: 增加
void sunpos_print(spa_data *spa)
{
 char msg[64];
        
 rt_kprintf("太阳位置@ %s %s:%d\r\n",__FILE__, __FUNCTION__, __LINE__);//当前行所在文件名、函数名、第**行代码           
 rt_kprintf("UTC TIME: \r\n"); 
 rt_kprintf("year %d ",spa->year);     //UTC输入: 4-digit year,    valid range: 0 to 6000, error code: 1
 rt_kprintf("month %d ",spa->month); //UTC输入: 2-digit month,         valid range: 1 to 12, error code: 2
 rt_kprintf("day %d ",spa->day);       //UTC输入: 2-digit day,           valid range: 1 to 31, error code: 3
 rt_kprintf("hour %d ",spa->hour);     //UTC输入: Observer local hour,   valid range: 0 to 24, error code: 4
 rt_kprintf("minute %d ",spa->minute); //UTC输入: Observer local minute, valid range: 0 to 59, error code: 5
 rt_kprintf("second %d ",spa->second); //UTC输入: Observer local second, valid range: 0 to 59, error code: 6
 rt_kprintf("timezone %d ",spa->timezone);    //输入: 当地Observer time zone (negative west of Greenwich)
                                            //       valid range: -18   to   18 hours,   error code: 7
 rt_kprintf("\r\n LOCATION: \r\n"); 
 sprintf(msg, "longitude %f ",spa->longitude);// 输入:当地经度Observer longitude (negative west of Greenwich)
                                            //           valid range: -180  to  180 degrees, error code: 8
 rt_kprintf("\r\n %s",msg);
 sprintf(msg, "latitude %f ",spa->latitude); // 输入:当地纬度Observer latitude (negative south of equator)
                                           //           valid range: -90   to   90 degrees, error code: 9
 rt_kprintf("\r\n %s",msg);
    //---------------------OUTPUT VALUES------------------------
 rt_kprintf("\r\n ndays %d ",spa->ndays);                     //UTC时间,从元旦(含)计,全年第几天

 sprintf(msg, "\r\n mean_solar_time %f ",spa->mean_solar_time); //输出:当地平太阳时, 由hhmmss计算,单位 分钟
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n error_time %f ",spa->error_time);           //时差:当地真太阳时与平太阳时之差,单位 分钟
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n apparent_solar_time %f ",spa->apparent_solar_time); //输出:当地太阳真时    0-24,单位 分钟
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n solar_hour_angle %f ",spa->solar_hour_angle);       //输出:当地太阳时角    -180~180度
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n solar_declination_angle %f ",spa->solar_declination_angle);  //输出:当地赤纬角      -23.45 ~ 23.45度
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n solar_altitude_angle %f ",spa->solar_altitude_angle);        //输出:当地太阳高度角  -90~90度
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n solar_azimuth_angle; %f ",spa->solar_azimuth_angle);         //输出:当地太阳方位角  -180~ 180度
 rt_kprintf("\r\n %s",msg); 
 sprintf(msg, "\r\n solar_hour_angle_sunrise %f ",spa->solar_hour_angle_sunrise);//输出:当地升起时刻的太阳时角-180~0度
 rt_kprintf("\r\n %s",msg);
 rt_kprintf("\r\n  ");
}
复制代码

 

上述程序使用了自己编制的时间格式转换程序。如下:

复制代码
#ifndef TIMEFORMAT_H
#define TIMEFORMAT_H 
#include "stm32g0xx_hal.h"
/*完成UTC与当地时间转换*/
typedef struct dateTime
{
  uint32_t time;// BCD码 hhmmss(时分秒)
    uint32_t date;// BCD码 ddmmyy(日月年)
} DateTime_Type;

void UTC2Local(DateTime_Type *p_DateTime_Type,int32_t timeZone);
void Local2UTC(DateTime_Type *p_DateTime_Type,int32_t timeZone);

uint8_t Bcd2ToByte(uint8_t Value);
uint8_t ByteToBcd2(uint8_t Value);

uint32_t Date2Days( uint8_t year, uint8_t month, uint8_t day);//返回总天数
uint8_t  Days2Date( int32_t days,uint8_t year, uint8_t* month, uint8_t* day);

uint8_t IsLeapYear(int16_t year);// 判断是否为闰年

/*算例*/
//  test_dateTime.time = 0x00042436;// BCD码 hhmmss(时分秒)
//    test_dateTime.date = 0x00010109;// BCD码 ddmmyy(日月年)
//  UTC2Local(&test_dateTime,-8);
//  Local2UTC(&test_dateTime,-8);    
#endif
复制代码

 

复制代码
#include <timeformat.h>

/**
  * @brief  Convert from 2 digit BCD to Binary.
  * @param  Value BCD value to be converted
  * @retval Converted word
  */
uint8_t Bcd2ToByte(uint8_t Value)
{
  uint32_t tmp;
  tmp = (((uint32_t)Value & 0xF0U) >> 4U) * 10U;
  return (uint8_t)(tmp + ((uint32_t)Value & 0x0FU));
}
/**
  * @brief  Convert from Binary to 2 digit BCD .
  * @param  Value BCD value to be converted
  * @retval Converted word
  */
uint8_t ByteToBcd2(uint8_t Value)
{
  uint16_t tmp1,tmp2;
    tmp1 =(uint16_t)Value;
    
    tmp2 = tmp1/10;
    tmp2 = tmp2<<4U;
    tmp2= tmp2&0x00F0;
    
    tmp1 = tmp1%10;
  return (uint8_t)( tmp1+tmp2);
}
/**
  * @brief  IsLeapYear
  * @param  year to be judged
  * @retval Is_Leap_Year 
  */
// 判断是否为闰年
uint8_t IsLeapYear(int16_t year)
{
    uint8_t  Is_Leap_Year;    
  Is_Leap_Year=0x00;    
    if((year%4==0)&&(year%100 != 0))
        Is_Leap_Year=0x01;//闰年
    else
    {
        if(year%400==0) Is_Leap_Year=0x01;//闰年
    }        
    return Is_Leap_Year;
}
/**
  * @brief  Date2Days
  * @param  year, month,day 整数
  * @retval days 
  */
uint32_t Date2Days( uint8_t year, uint8_t month, uint8_t day)
{
    const uint8_t Leap_Year_month_days[]    ={31,29,31,30,31,30,31,31,30,31,30,31};
    const uint8_t Ordinary_Year_month_days[]={31,28,31,30,31,30,31,31,30,31,30,31};    
    uint8_t  Is_Leap_Year;    
    uint32_t  totalDays;
    uint8_t   i;
    if((year<=0)||(year>100)) return 0;
    if((month<=0)||(month>12)) return 0;    
    
    Is_Leap_Year = IsLeapYear(year);    
    
    if(Is_Leap_Year==0x01){
         if((day<=0)||(day>Leap_Year_month_days[month-1])    ) return 0;
    }
    else{
         if((day<=0)||(day>Ordinary_Year_month_days[month-1])) return 0;        
    }
    
    totalDays =0;
    for(i=0;i<month-1;i++)
    {
        if(Is_Leap_Year==0x01){
            totalDays += Leap_Year_month_days[i];
        }
        else{            
            totalDays += Ordinary_Year_month_days[i];
        }
    }
    
    totalDays +=day;
    
    return totalDays;
}

/**
  * @brief  Days2Date
  * @param  days(不多于当年天数),year
  * @retval month,day 整数
  */
uint8_t Days2Date( int32_t days,uint8_t year, uint8_t* month, uint8_t* day)
{
    const uint8_t Leap_Year_month_days[]    ={31,29,31,30,31,30,31,31,30,31,30,31};
    const uint8_t Ordinary_Year_month_days[]={31,28,31,30,31,30,31,31,30,31,30,31};    
    uint8_t  Is_Leap_Year;    
    uint32_t  totalDays;
    uint8_t   i;
    
    if((year<=1)||(year>100)) return 1;
    
    Is_Leap_Year = IsLeapYear(year);    
    
  if(Is_Leap_Year==0x01)
    {
      if( days >366){
          return 2;
        }
    }
    else
    {
      if( days >365){
     return 2;
        }    
    }
    
    totalDays =0;
    for(i=0;i<12;i++){
        if(Is_Leap_Year==0x01){
             totalDays += Leap_Year_month_days[i];
             if((days<=totalDays)&&( days+ Leap_Year_month_days[i]>totalDays ) ) 
             {
                 *month = i+1;//判断出当前月
                 break;
             }
        }
        else{
             totalDays += Ordinary_Year_month_days[i];
             if((days<=totalDays)&&( days+ Ordinary_Year_month_days[i]>totalDays ) ) 
             {
                 *month = i+1;//判断出当前月
                 break;
             }    
        }
  }
    
  totalDays =0;
    for(i=0;i<*month-1;i++)
    {
        if(Is_Leap_Year==0x01){
            totalDays += Leap_Year_month_days[i];
        }
        else{            
            totalDays += Ordinary_Year_month_days[i];
        }
    }
    *day = days- totalDays;// 计算出当月第几日
    
    return 0;
}
/**
  * @brief  Convert from UTC BCD to LOCAL.
  * @param   time Zone, 东半球正
  * @retval Converted word
  * uint32_t time;//GPS模块 BCD码 hhmmss(时分秒)
    * uint32_t date;//GPS模块 BCD码 ddmmyy(日月年)
  */
void UTC2Local(DateTime_Type *p_DateTime_Type,int32_t timeZone)
{
   uint8_t year;
   uint8_t month;
   uint8_t day;
   uint8_t hour;
   uint8_t minute;
   uint8_t second;    
     int32_t temp;
     int32_t totalMinutes;
     uint16_t totalDays;    
     uint8_t  Is_Leap_Year;    
    
     temp = p_DateTime_Type->date%256;
     year = Bcd2ToByte(temp);
    
   temp = p_DateTime_Type->date/256;    
   temp = temp%256;    
     month = Bcd2ToByte(temp);
    
     temp = p_DateTime_Type->date/(256*256);    
   temp = temp%256;    
     day = Bcd2ToByte(temp);

     temp = p_DateTime_Type->time%256;
     second = Bcd2ToByte(temp);    
    
     temp = p_DateTime_Type->time/256;
     temp = temp%256;    
     minute = Bcd2ToByte(temp);    
     
     temp = p_DateTime_Type->time/(256*256);
     temp = temp%256;    
     hour = Bcd2ToByte(temp);    
     
     totalDays = Date2Days( year, month, day);
     
     totalMinutes = (totalDays-1)*24*60; 
     totalMinutes = totalMinutes+ hour*60 + minute;
     
     totalMinutes = totalMinutes + 4*15*timeZone;// 以分钟为单位,计算当地时间
     
     if(totalMinutes < 0) 
     {
         Is_Leap_Year= IsLeapYear( year-1);     
         if(Is_Leap_Year==0x01){
             totalMinutes = totalMinutes + 366*24*60;
         }
         else {
             totalMinutes = totalMinutes + 365*24*60;             
         }
         year = year -1;
         goto next_UTC2Local;
     }
     if(totalMinutes > 0) 
     {
          Is_Leap_Year= IsLeapYear( year);
         if(Is_Leap_Year==0x01){
             if(totalMinutes> 366*24*60){
                  totalMinutes = totalMinutes - 366*24*60;
                  year = year+1;
             }
         }
         else {
             if(totalMinutes> 365*24*60){
                  totalMinutes = totalMinutes - 365*24*60;
                  year = year+1;
             }     
         }     
     }
     
next_UTC2Local:     
     totalDays = totalMinutes/(24*60)+1;
     totalMinutes = totalMinutes%(24*60);
     hour   = totalMinutes/60;
     minute = totalMinutes%60;
     
     Days2Date( totalDays,year, &month, &day);
     
     year  = ByteToBcd2(year);
     month = ByteToBcd2(month);
     day   = ByteToBcd2(day);
     hour  = ByteToBcd2(hour);
     minute= ByteToBcd2(minute);
     second= ByteToBcd2(second);
     
     p_DateTime_Type->date = year       + (month<<8)  + (day<<16);//GPS模块 BCD码 ddmmyy(日月年)
     p_DateTime_Type->time = (hour<<16) + (minute<<8) +second ;//GPS模块 BCD码 hhmmss(时分秒)
}
/**
  * @brief  Convert from LOCAL to UTC.
  * @param   timeZone, 东半球正
  * @retval Converted word
  */
void Local2UTC(DateTime_Type *p_DateTime_Type,int32_t timeZone)
{
  uint8_t year;
   uint8_t month;
   uint8_t day;
   uint8_t hour;
   uint8_t minute;
   uint8_t second;    
     int32_t temp;
     int32_t totalMinutes;
     uint16_t totalDays;    
     uint8_t  Is_Leap_Year;    
    
     temp = p_DateTime_Type->date%256;
     year = Bcd2ToByte(temp);
    
   temp = p_DateTime_Type->date/256;    
   temp = temp%256;    
     month = Bcd2ToByte(temp);
    
     temp = p_DateTime_Type->date/(256*256);    
   temp = temp%256;    
     day = Bcd2ToByte(temp);

     temp = p_DateTime_Type->time%256;
     second = Bcd2ToByte(temp);    
    
     temp = p_DateTime_Type->time/256;
     temp = temp%256;    
     minute = Bcd2ToByte(temp);    
     
     temp = p_DateTime_Type->time/(256*256);
     temp = temp%256;    
     hour = Bcd2ToByte(temp);    
     
     totalDays = Date2Days( year, month, day);
     
     totalMinutes = (totalDays-1)*24*60; 
     totalMinutes = totalMinutes+ hour*60 + minute;
     
     totalMinutes = totalMinutes - 4*15*timeZone;// 以分钟为单位,计算UTC时间
     
     if(totalMinutes < 0) 
     {
         Is_Leap_Year= IsLeapYear( year-1);     
         if(Is_Leap_Year==0x01){
             totalMinutes = totalMinutes + 366*24*60;
         }
         else {
             totalMinutes = totalMinutes + 365*24*60;             
         }
         year = year -1;
         goto next_Local2UTC;
     }
     if(totalMinutes > 0) 
     {
          Is_Leap_Year= IsLeapYear( year);
         if(Is_Leap_Year==0x01){
             if(totalMinutes> 366*24*60){
                  totalMinutes = totalMinutes - 366*24*60;
                  year = year+1;
             }
         }
         else {
             if(totalMinutes> 365*24*60){
                  totalMinutes = totalMinutes - 365*24*60;
                  year = year+1;
             }     
         }
     }
     
next_Local2UTC:     
     totalDays = totalMinutes/(24*60)+1;
     totalMinutes = totalMinutes%(24*60);
     hour   = totalMinutes/60;
     minute = totalMinutes%60;
     
     Days2Date( totalDays,year, &month, &day);
     
     year  = ByteToBcd2(year);
     month = ByteToBcd2(month);
     day   = ByteToBcd2(day);
     hour  = ByteToBcd2(hour);
     minute= ByteToBcd2(minute);
     second= ByteToBcd2(second);
     
     p_DateTime_Type->date = year       + (month<<8)  + (day<<16);//GPS模块 BCD码 ddmmyy(日月年)
     p_DateTime_Type->time = (hour<<16) + (minute<<8) +  second ; //GPS模块 BCD码 hhmmss(时分秒)
}
复制代码

 

posted @   辛河  阅读(75)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示