STM32开发 -- UTC、UNIX时间戳、北京时间之间的转换

发布者:翠绿山水最新更新时间:2019-09-02 来源: eefocus关键字:STM32  UTC  UNIX时间戳  北京时间  转换 手机看文章 扫描二维码
随时随地手机看文章

我碰到的问题,GPS上UTC时间转北京时间和STM32上UNIX时间戳转北京时间。

这部分之前讲RTC和GPS的时候有涉及到一部分。

具体的RTC如何得到UNIX时间戳,和GNRMC如何解析得到UTC时间可以参看一下。

参看:STM32开发 – RTC详解

参看:STM32开发 – GPS模块开发详解


扩展:C语言再学习 – 时间函数


这里主要看三者转换方法:


一、UTC时间转换为北京时间

参看:UTC时间转换为北京时间


时间类型结构体


//UTC时间信息

__packed typedef struct  

{     

  uint16_t year; //年份

uint8_t month; //月份

uint8_t date; //日期

uint8_t hour; //小时

uint8_t min; //分钟

uint8_t sec; //秒钟

}nmea_time;


UTC时间转任意时区时间


其中,北京时间 = UTC time + 8 hours


void UTC_to_BJtime(nmea_time* utc_time, int8_t timezone)

{

int year,month,day,hour;

    int lastday = 0; //last day of this month

    int lastlastday = 0; //last day of last month


    year = utc_time->year; //utc time

    month  = utc_time->month;

    day = utc_time->date;

    hour = utc_time->hour + timezone; 

    if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){

        lastday = 31;

        if(month == 3){

            if((year%400 == 0)||(year%4 == 0 && year%100 != 0)) //if this is lunar year

                lastlastday = 29;

            else

                lastlastday = 28;

        }

        if(month == 8)

            lastlastday = 31;

    }

    else if(month == 4 || month == 6 || month == 9 || month == 11){

        lastday = 30;

        lastlastday = 31;

    }

    else{

        lastlastday = 31;

        if((year%400 == 0)||(year%4 == 0 && year%100 != 0))

            lastday = 29;

        else

            lastday = 28;

    }


    if(hour >= 24){ // if >24, day+1

            hour -= 24;

            day += 1; 


            if(day > lastday){ // next month,  day-lastday of this month

                day -= lastday;

                month += 1;


                if(month > 12){ // next year , month-12

                    month -= 12;

                    year += 1;

                }

            }

        }

    if(hour < 0){ // if <0, day-1

            hour += 24;

            day -= 1; 

            if(day < 1){   // month-1, day=last day of last month

                day = lastlastday;

                month -= 1;

                if(month < 1){ // last year , month=12

                    month = 12;

                    year -= 1;

                }

            }

        }

   // transfer value to NMEA_result.local_time

NMEA_result.local_time.year  = year;

NMEA_result.local_time.month = month;

NMEA_result.local_time.date  = day;

NMEA_result.local_time.hour  = hour;

NMEA_result.local_time.min = utc_time->min;

NMEA_result.local_time.sec = utc_time->sec;

}


二、UNIX Time 时间戳 与 北京时间 相互转换

参看:UNIX Time 时间戳 与 北京时间 相互转换


typedef struct t_xtime {

  int year; int month;  int day;  

  int hour; int minute;  int second;

} _xtime ;

 

#define xMINUTE   (60             ) //1分的秒数

#define xHOUR      (60*xMINUTE) //1小时的秒数

#define xDAY        (24*xHOUR   ) //1天的秒数

#define xYEAR       (365*xDAY   ) //1年的秒数


1、将localtime(UTC+8北京时间)转为UNIX TIME,以1970年1月1日为起点

unsigned int  xDate2Seconds(_xtime *time)

{

  static unsigned int  month[12]={

    /*01月*/xDAY*(0),

    /*02月*/xDAY*(31),

    /*03月*/xDAY*(31+28),

    /*04月*/xDAY*(31+28+31),

    /*05月*/xDAY*(31+28+31+30),

    /*06月*/xDAY*(31+28+31+30+31),

    /*07月*/xDAY*(31+28+31+30+31+30),

    /*08月*/xDAY*(31+28+31+30+31+30+31),

    /*09月*/xDAY*(31+28+31+30+31+30+31+31),

    /*10月*/xDAY*(31+28+31+30+31+30+31+31+30),

    /*11月*/xDAY*(31+28+31+30+31+30+31+31+30+31),

    /*12月*/xDAY*(31+28+31+30+31+30+31+31+30+31+30)

  };

  unsigned int  seconds = 0;

  unsigned int  year = 0;

  year = time->year-1970;       //不考虑2100年千年虫问题

  seconds = xYEAR*year + xDAY*((year+1)/4);  //前几年过去的秒数

  seconds += month[time->month-1];      //加上今年本月过去的秒数

  if( (time->month > 2) && (((year+2)%4)==0) )//2008年为闰年

    seconds += xDAY;            //闰年加1天秒数

  seconds += xDAY*(time->day-1);         //加上本天过去的秒数

  seconds += xHOUR*time->hour;           //加上本小时过去的秒数

  seconds += xMINUTE*time->minute;       //加上本分钟过去的秒数

  seconds += time->second;               //加上当前秒数
 seconds -= 8 * xHOUR;

  return seconds;

}


2、将UNIX时间转为UTC+8 即北京时间

//UNIX转为UTC 已进行时区转换 北京时间UTC+8

void xSeconds2Date(unsigned long seconds,_xtime *time )

{

    static unsigned int month[12]={

        /*01月*/31, 

        /*02月*/28, 

        /*03月*/31, 

        /*04月*/30, 

        /*05月*/31, 

        /*06月*/30, 

        /*07月*/31, 

        /*08月*/31, 

        /*09月*/30, 

        /*10月*/31, 

        /*11月*/30, 

        /*12月*/31 

    };

    unsigned int days; 

    unsigned short leap_y_count; 

    time->second      = seconds % 60;//获得秒 

    seconds          /= 60; 

    time->minute      =  seconds % 60;//获得分 

    seconds          += 8 * 60 ;        //时区矫正 转为UTC+8 bylzs

    seconds          /= 60; 

    time->hour        = seconds % 24;//获得时 

    days              = seconds / 24;//获得总天数 

    leap_y_count = (days + 365) / 1461;//过去了多少个闰年(4年一闰) 

    if( ((days + 366) % 1461) == 0) 

    {//闰年的最后1天 

        time->year = 1970 + (days / 366);//获得年 

        time->month = 12;              //调整月 

        time->day = 31; 

        return; 

    } 

    days -= leap_y_count; 

    time->year = 1970 + (days / 365);     //获得年 

    days %= 365;                       //今年的第几天 

    days = 01 + days;                  //1日开始 

    if( (time->year % 4) == 0 ) 

    { 

        if(days > 60)--days;            //闰年调整 

        else 

        { 

            if(days == 60) 

            { 

                time->month = 2; 

                time->day = 29; 

                return; 

            } 

        } 

    } 

    for(time->month = 0;month[time->month] < days;time->month++) 

    { 

        days -= month[time->month]; 

    } 

    ++time->month;               //调整月 

    time->day = days;           //获得日 

}


3、UTC(字符串)转UNIX时间

/*******************************************************************************

* Function Name  : ConvertTimeToSecond

* Description    : Convert GPS Date to Log buffer.

* Input          : @date: format 'DDMMYY,HHMMSS.SSS'

* Output         : None

* Return         : Sencod

*******************************************************************************/

static u32 ConvertDateToSecond(const u8 *date)

{

u32 sencods = 0;

u16 temp = 1970;

u16 days = 0;

if(NULL == date) {

return 0;

}

//year

temp = (date[4] - 0x30) * 10 + (date[5] - 0x30) + 2000;

if(0 == (temp % 4)) {

days += 1;

}

temp -= 1;

//UTC time start 1970

for(; temp >= 1970; temp--) {

if(temp % 4) {

days += 365;

} else {

//leap year

days += 366;

[1] [2]
关键字:STM32  UTC  UNIX时间戳  北京时间  转换 引用地址:STM32开发 -- UTC、UNIX时间戳、北京时间之间的转换

上一篇:STM32开发 -- 看门狗详解
下一篇:STM32开发 -- 外部中断详解

推荐阅读最新更新时间:2024-11-09 05:15

STM32区别 SYSCLK和HCLK和PCLK1和PCLK2(system_stm32f10x.c中PCLK1才进行2分频设置)
system_stm32f10x.c system_stm32f10x.cstatic void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ /* Enable HSE */ RCC- CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reach
[单片机]
<font color='red'>STM32</font>区别 SYSCLK和HCLK和PCLK1和PCLK2(system_stm32f10x.c中PCLK1才进行2分频设置)
STM32串口USART配置、发送与接收
一、配置时钟:GPIO时钟、串口时钟、复用引脚时钟 二、配置GPIO结构体 三、配置串口结构体 //串口初始化示例 void usart_init(void) { //创建结构体 GPIO_InitTypeDef gpioinitStructure; USART_InitTypeDef usartinitStructure; NVIC_InitTypeDef NVICinitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置时钟 RCC_APB2PeriphClockCmd(RCC_APB2Pe
[单片机]
<font color='red'>STM32</font>串口USART配置、发送与接收
STM32入门学习笔记之RTC实验(下)
(2)创建rtc.c文件并输入以下代码。 #include rtc.h /*************************************************** Name :RTC_Init Fuction :RTC初始化 Parameter :None Return :None ***************************************************/ void RTC_Init() { if( BKP- DR1!=0x5050 ) { RCC- APB1ENR |= 1 28 ; //使能PWR时钟
[单片机]
如何在STM32单片机上移植FreeRTOS
首先在网上看到大部分移植FreeRTOS 都是选择修改他的启动文件,我个人感觉这样不是很好,毕竟是汇编,当你采用不同的芯片型号时,又要修改不同的xx.S文件,所以我选择修改FreeRTOSconfig.h文件。 1. 下载STM32官方源码:我的是基于V3.5的官方库(有工程模板的可以不用)。 2. 搭建好一个MDK的工程,我这里采用的是野火的工 程。 3. 在工程模板目录下新建一个FreeRTOS文件夹,在FreeRTOS文件夹在建一个includewen文件夹(存放.h文件,方便管理)。 (1)从FreeRTOS7.0.2 的源文件中找到 croutine.c, timers.c,list.c, queue.c, task
[单片机]
gd32和stm32程序可以互用吗?
GD32和STM32是两种不同的芯片系列,相同点是都属于ARM Cortex-M系列芯片。虽然它们有相似的架构和指令集,但是由于它们来自不同的厂商,所以它们之间仍然存在一些差异。因此,GD32和STM32之间不能直接互用程序。 首先,GD32和STM32之间的主要差异在于硬件平台。GD32和STM32的硬件平台不完全相同,存在一些不同之处,例如引脚定义、时钟控制、中断控制等。这些差异会影响程序在不同硬件平台上的运行。因此,如果要实现程序互用,需要在代码中加入条件编译和适配。 其次,GD32和STM32之间的软件支持也有所不同。虽然它们都遵循ARM Cortex-M系列的指令集,但它们的官方开发环境、库文件和驱动程序可能存在差异。因
[单片机]
STM32入门学习路线
  可以说就目前的市场需求来看,stm32在单片机领域已经拥有了绝对的地位,51什么的已经过时了也只能拿来打基础了,最后依然会转到stm32来,也正是因为这样stm32的学习者越来越多,其中不难发现绝大部分的stm32的学习者是在入门阶段的,所以今天我们就来聊聊stm32的入门学习路线。   先来看个图,相信会有所了解。   首先学习stm32 不管是C语言还是汇编肯定跑不了的所以C语言一样要打好基础,尤其是C语言中的指针,结构体,循环 等等一些最基础的知识你要能够熟练应用,要不然对于从事stm32开发的难度是非常大的。   针对C语言我给大家推荐一个视频资料虽然是某某机构录的资料不过讲的倒是很详细值得一看   C语言
[单片机]
STM32 TouchGFX部分控件功能测试
我这次主要测试了TextArea,界面按键响应、动态图形【dynamicgraph】、模拟时钟【Analog Clock】、进度条显示以及软件上添加虚拟函数的实现。涉及的界面有下面几个:【仅为测试,界面美丑略过】 第一个要注意的地方。 我使用的IDE是STM32CubeIDE。当我在相应hpp头文件里添加虚拟函数声明时,需要在IDE环境里专门对该头文件做个save操作,不然在cpp函数里写好相应函数后编译时总提示没有做函数声明。 举个例子说下,比方我要在Screen1View.cpp写一个IncDuty()函数。 我们需在其对应的头文件里加上虚拟函数的声明。在头文件里添加了该虚拟函数声明后,需要手动对该文件做个SA
[单片机]
<font color='red'>STM32</font> TouchGFX部分控件功能测试
STM32的基本概念及中断应用
1、基本概念 ARMCoetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved