Unix时间戳

江科大学习记录

Unix时间戳

  • Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒
  • 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量
  • 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间
    在这里插入图片描述
    UTC/GMT
  • GMT(Greenwich Mean Time)格林尼治标准时间是一种以地球自转为基础的时间计量系统。它将地球自转一周的时间间隔等分为24小时,以此确定计时标准
  • UTC(Universal Time Coordinated)协调世界时是一种以原子钟为基础的时间计量系统。它规定铯133原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间为1秒。当原子钟计时一天的时间与地球自转一周的时间相差超过0.9秒时,UTC会执行闰秒来保证其计时与地球自转的协调一致
    时间戳转换
    C语言的time.h模块提供了时间获取和时间戳转换的相关函数,可以方便地进行秒计数器、日期时间和字符串之间的转换
    在这里插入图片描述
    秒计数器转换为日期时间(格林尼治时间)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t timer;
struct tm *time_Structue;
int main()
{
	
	timer = time(NULL);
    printf("%d\n",timer);
    time_Structue = gmtime(&timer);
    printf("%d年-%d月-%d日-%d时-%d分",time_Structue->tm_year+1900,time_Structue->tm_mon+1,time_Structue->tm_mday,time_Structue->tm_hour,time_Structue->tm_sec);
	printf("\n星期%d\n",time_Structue->tm_wday);
    system("pause");
	return 0;
}

blog.csdnimg.cn/2b384342094842869d2d1514b6082a53.png)

秒计数器转换为日期时间(当地时间)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t timer;
struct tm *time_Structue;
int main()
{
	
	timer = time(NULL);
    printf("%d\n",timer);
    time_Structue = localtime(&timer);
    printf("%d年-%d月-%d日-%d时-%d分",time_Structue->tm_year+1900,time_Structue->tm_mon+1,time_Structue->tm_mday,time_Structue->tm_hour,time_Structue->tm_sec);
	printf("\n星期%d\n",time_Structue->tm_wday);
    system("pause");
	return 0;
}

在这里插入图片描述
日期时间转换为秒计数器(当地时间)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t timer;
struct tm *time_Structue;
int main()
{
	
	timer = time(NULL);
    printf("%d\n",timer);
    time_Structue = localtime(&timer);
    printf("%d年-%d月-%d日-%d时-%d分",time_Structue->tm_year+1900,time_Structue->tm_mon+1,time_Structue->tm_mday,time_Structue->tm_hour,time_Structue->tm_sec);
	printf("\n星期%d\n",time_Structue->tm_wday);
    
    timer = mktime(time_Structue);
    printf("转换为秒计数器:%d\n",timer);
    system("pause");
	return 0;
}

在这里插入图片描述
日期时间转换为字符串(默认格式)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t timer;
struct tm *time_Structue;
char* str;
int main()
{
	
	timer = time(NULL);
    printf("%d\n",timer);
    time_Structue = localtime(&timer);
    printf("%d年-%d月-%d日-%d时-%d分",time_Structue->tm_year+1900,time_Structue->tm_mon+1,time_Structue->tm_mday,time_Structue->tm_hour,time_Structue->tm_sec);
	printf("\n星期%d\n",time_Structue->tm_wday);
    
    timer = mktime(time_Structue);
    printf("转换为秒计数器:%d\n",timer);
    
    str = asctime(time_Structue);
    printf("字符串:%s\n",str);
    system("pause");
	return 0;
}

在这里插入图片描述

在这里插入图片描述

BKP简介

  • BKP(Backup Registers)备份寄存器

  • BKP可用于存储用户应用程序数据。当VDD(2.0—3.6V)电源被切断,他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒,或系统复位或电源复位时,他们也不会被复位

  • TAMPER引脚产生的侵入事件将所有备份寄存器内容清除

  • RTC引脚输出RTC校准时钟、RTC闹钟脉冲或者秒脉冲

  • 存储RTC时钟校准寄存器

  • 用户数据存储容量:

    20字节(中容量和小容量)/ 84字节(大容量和互联型)

BKP基本结构
在这里插入图片描述

RTC简介

  • RTC(Real Time Clock)实时时钟

  • RTC是一个独立的定时器,可为系统提供时钟和日历的功能

  • RTC和时钟配置系统处于后备区域,系统复位时数据不清零,VDD(2.0~3.6V)断电后可借助VBAT(1.8—3.6V)供电继续走时

  • 32位的可编程计数器,可对应Unix时间戳的秒计数器

  • 20位的可编程预分频器,可适配不同频率的输入时钟

  • 可选择三种RTC时钟源:

    HSE时钟除以128(通常为8MHz/128)
    LSE振荡器时钟(通常为32.768KHz)
    LSI振荡器时钟(40KHz)

RTC框图
在这里插入图片描述
输出给TR_CLK的频率为1Hz,计时周期为1s,让RTC_CNT按秒计数
RTC基本结构
在这里插入图片描述
硬件电路
在这里插入图片描述
RTC操作注意事项

  • 执行以下操作将使能对BKP和RTC的访问:

    设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟
    设置PWR_CR的DBP,使能对BKP和RTC的访问

  • 若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1

  • 必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器

  • 对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是1时,才可以写入RTC寄存器
    案例:读写BKP寄存器

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "key.h"
#include "OLED.h"

uint16_t ArrayWrite[] = {0x1234,0x4567};
uint16_t ArrayRead[2];

void RCC_Clock_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
}

void OLED_Test(void)
{
	char *str = "hello world";
	OLED_ShowString(1,2,str);
}

int main(void)
{
	uint16_t keyNum;;
	RCC_Clock_Init();
	Key_Init();
	OLED_Init();
	OLED_Test();
	
	PWR_BackupAccessCmd(ENABLE);
	
	//BKP_WriteBackupRegister(BKP_DR1,0x1234);
	
	OLED_ShowString(2,1,"W:");
	OLED_ShowString(3,1,"R:");
	while(1){
		keyNum = Key_Scan();
		if(keyNum == 1){
			ArrayWrite[0]++;
			ArrayWrite[1]++;
			BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);
			BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);
			OLED_ShowHexNum(2,3,ArrayWrite[0],4);
			OLED_ShowHexNum(2,8,ArrayWrite[1],4);

			
		}else {
			ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);
			ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);
			
			OLED_ShowHexNum(3,3,ArrayRead[0],4);
			OLED_ShowHexNum(3,8,ArrayRead[1],4);
			
		}
	}	
}


案例二:RTC实时时钟
main

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"
int main(void)
{


	OLED_Init();
	MyRTC_Init();
	//char *str = "hello world";
	OLED_ShowString(1,1,"Date:XXXX-XX-XX");
	OLED_ShowString(2,1,"Tim:XX-XX-XX");
	OLED_ShowString(4,1,"DIV:");
	
	while(1){

		MyRTC_ReadTime();
		OLED_ShowNum(1,6,TimeData.year,4);
		OLED_ShowNum(1,11,TimeData.mon,2);
		OLED_ShowNum(1,14,TimeData.day,2);
		OLED_ShowNum(2,5,TimeData.hour,2);
		OLED_ShowNum(2,8,TimeData.min,2);
		OLED_ShowNum(2,11,TimeData.sec,2);
		OLED_ShowNum(3,1,RTC_GetCounter(),10);
		OLED_ShowNum(4,5,RTC_GetDivider(),10);
	}
	
	
	
}


MyRTC.c

#include "MyRTC.h"
#include "time.h"

Time TimeData = {
	2023,
	1,
	1,
	23,
	59,
	55,		
};

void MyRTC_SetTime(void)
{
	time_t time_cnt;
	struct tm time_data;
	time_data.tm_year = TimeData.year - 1900;
	time_data.tm_mon = TimeData.mon - 1;
	time_data.tm_mday = TimeData.day;
	time_data.tm_hour = TimeData.hour;
	time_data.tm_min = TimeData.min;
	time_data.tm_sec = TimeData.sec;
	
	time_cnt = mktime(&time_data) - (8*60*60);
	RTC_SetCounter(time_cnt);
	RTC_WaitForLastTask();
}


void MyRTC_ReadTime(void)
{
	time_t time_cnt;
	struct tm time_data;
	time_cnt = RTC_GetCounter()+(8*60*60);
	time_data = *localtime(&time_cnt);
	
	TimeData.year = time_data.tm_year+1900;
	TimeData.mon = time_data.tm_mon+1;
	TimeData.day = time_data.tm_mday;
	TimeData.hour  =time_data.tm_hour;
	TimeData.min = time_data.tm_min;
	TimeData.sec = time_data.tm_sec;	
}

void MyRTC_Init(void)
{
	//设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	
	//设置PWR_CR的DBP,使能对BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	if(BKP_ReadBackupRegister(BKP_DR1) != 0xAAAA){
		
					//打开LSE
			RCC_LSEConfig(RCC_LSE_ON);
			while(RCC_GetFlagStatus(RCC_FLAG_LSERDY == RESET));
			RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
			RCC_RTCCLKCmd(ENABLE);
			

			
			//必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1
			RTC_WaitForSynchro();
			//仅当RTOFF状态位是1时,才可以写入RTC寄存器
			RTC_WaitForLastTask();
			
			RTC_SetPrescaler(32768 - 1);
			RTC_WaitForLastTask();
			
			MyRTC_SetTime();
			BKP_WriteBackupRegister(BKP_DR1,0xAAAA);
	}else {
		
			//必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1
			RTC_WaitForSynchro();
			//仅当RTOFF状态位是1时,才可以写入RTC寄存器
			RTC_WaitForLastTask();
		
	}
	

}





#ifndef _MYRTC_H
#define _MYRTC_H
#include "stm32f10x.h"                  // Device header
#include "Delay.h"



void MyRTC_Init(void);
void MyRTC_SetTime(void);
void MyRTC_ReadTime(void);
typedef struct{
	uint16_t year;
	uint16_t mon;
	uint16_t day;
	uint16_t hour;
	uint16_t min;
	uint16_t sec;
	
}Time;
extern Time TimeData;
#endif




  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值