HAL库RTC时间戳和日期之间的相互转化

 1.RTC初始化 (为了兼容有无外部晶振程序都可正常运行,增加和更改了初始化相关函数)

void hal_rtc_init(void)
{
    uint32_t tickstart = 0;
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    HAL_PWR_EnableBkUpAccess();   //使能后备域访问
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);设置外部低速晶振驱动能力
        
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;    
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct.LSEState);  ///打开外部低速晶振
    
    tickstart = HAL_GetTick();
    while (READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)  /*读取LSE晶振准备状态*/
    {
      lse_check_flag = 1;
      if ((HAL_GetTick() - tickstart) > LSE_CHECK_TIME)  ///当准备时间大于LSE_CHECK_TIME时间   那么外部低速晶振检测失败 rtc使用内部低速晶振
      {
            lse_check_flag = 0;  
            break;
      }
    }
    if(lse_check_flag)  ///检测成功
    {
        if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)  ///设置外部晶振
        {
            Error_Handler();
        }
    }
    MX_RTC_Init();  /初始化rtc
}

2.lse_check_flag主要用在下面函数中进行RTC的时钟配置,

void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspInit 0 */
    if(lse_check_flag == 0) ///外部低速时钟检测失败    那么将内部低速时钟作为RTC时钟源
    {
      PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
      PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

      if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
      {
        Error_Handler();
      }

      /* RTC clock enable */
      __HAL_RCC_RTC_ENABLE();
      __HAL_RCC_RTCAPB_CLK_ENABLE();
    }
    else  ///检测成功  那么将外部低速时钟作为时钟源
    {

  /* USER CODE END RTC_MspInit 0 */

  /** Initializes the peripherals clocks
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* RTC clock enable */
    __HAL_RCC_RTC_ENABLE();
    __HAL_RCC_RTCAPB_CLK_ENABLE();
  /* USER CODE BEGIN RTC_MspInit 1 */
    }
  /* USER CODE END RTC_MspInit 1 */
  }
}

3.时间戳和日期之间的相互转换

时间戳计算调用了头文件"time.h"函数,刚开始调用了gmtime这个函数,但是返回指针一直是NULL,后来参考在Keil MDK中无法使用gmtime函数进行时间戳转换_keil 5 时间戳-CSDN博客文章浏览阅读2.3k次,点赞4次,收藏11次。硬件平台STM32,软件平台Keil MDK 5.18由于项目中需要用到UNIX时间戳和日历的来回转换,于是想到C库函数里面有现成的函数可以使用。于直接使用mktime和gmtime两个函数进行时间戳转换,前者把日历转为时间戳,后者把时间戳转为日历。但是程序运行起来发现,gmtime得到的日历数据为乱码!!!经过调试才发现,这个函数返回值是NULL啊!!!查看反汇编代码,简直惊呆,这是什么鬼操作?汇编代码没有函数跳转,取而代之的是MOVS R0, #0_keil 5 时间戳https://blog.csdn.net/qq446252221/article/details/111625957,调用了localtime这个函数,gmtime和localtime的区别就是,gmtime返回的是GMT标准时间,而localtime返回的是本地时间。

何为本地时间?那就是带时区转换的时间,比如北京时间是东8区,与GMT时间相差8小时。

然而MDK库函数并没有直接设置时区的函数,因此locatime返回的仍然是GMT时间。

所以在使时localtime的时候,要先把时间戳加上28800秒(8小时)再进行转换,就能得到北京时间。

1)时间戳转换为日期:

/**
* @brief timestamp_set_clock 将时间戳转化为时间
* @param timestamp 需要转化的时间戳
* @param t 指向获取时间变量的指针
* @retval null
*/
static void timestamp_to_data(uint32_t timestamp,ts_rtc *t)
{
    struct tm *timeinfo = NULL;
    time_t t_stamp = 0;

    t_stamp = (time_t)(timestamp + 28800);   
    timeinfo = localtime(&t_stamp);    
    t->Year = timeinfo->tm_year + 1900 - 2000;   timeinfo得到的年份是从1900年开始   t.Year是从2000年开始
    t->Month = timeinfo->tm_mon + 1;   ///timeinfo的月份是从0开始  所以加一
    t->Date = timeinfo->tm_mday;
    t->Hours = timeinfo->tm_hour;
    t->Minutes = timeinfo->tm_min;
    t->Seconds = timeinfo->tm_sec;
}

timestamp + 28800,时间戳在原有的基础上加了28800也就是8小时,因为北京时间比标准时间快了8小时,

2)日期转换为时间戳:

/**
* @brief get_timestamp_value 将当前时间转化为时间戳
* @param timestamp 指向获取时间戳变量指针
* @retval null
*/
static void get_timestamp_value(uint32_t *timestamp)
{
    ts_rtc date = {0};  
    time_t times;
    struct tm tms;
    hal_get_DateTime(&date);  获取当前时间
    tms.tm_year = date.Year + 2000 - 1900; //C库函数的年份是从1900开始计算 date.Year是从2000年开始的,所以加上2000-1900
    tms.tm_mon  = date.Month - 1;   //C库函数的月份是用0表示1月
    tms.tm_mday = date.Date;
    tms.tm_hour = date.Hours;
    tms.tm_min  = date.Minutes;
    tms.tm_sec  = date.Seconds;
    times = mktime(&tms);
    *timestamp = times - 28800;    //北京时间:东8区偏移值
}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值