目录
一.时间戳
二.BKP简介
三.RTC外设简介
编辑四.相关寄存器
五.相关函数
六.代码实现
(1)读写备份寄存器
(2)实时时钟
一.时间戳
最早在Unix系统上使用
Linux,Windos,安卓的底层计时系统
好处:
1.简化硬件电路,直接采样一个秒寄存器来进行存储
2.在进行一些时间间隔的计算时非常方便
3.存储较方便,一个变量即可
但比较占用软件资源,需要进行秒分时年月日计算
STM32内部定义的变量、是一个无符号的32为整形数据,可以持续到2106年
每次产生闰秒时,时间戳的时间和标准时间会产生一秒的偏差
二.BKP简介
后备寄存器
VBAT(V Battery)备用电池电源
TAMPER引脚,对应PC-13-TAMPER-RTC,对应PC13引脚,可以用于设计侵入检测功能
校准时钟可以对内部RTC微小误差进行校准,可以配合校准寄存器
闹钟脉冲或者秒脉冲,可以输出为其他设备提供信号
三.RTC外设简介
在51中,DS1302是外设的 RTC芯片,可以进行独立计时
而在STM32内部,具有RTC外设
高速时钟供内部程序运行和主要外设使用
低速时钟供RTC,看门狗使用,LSE时钟为了省电默认是关闭的
四.相关寄存器
设计成16位可以简化电路设计
五.相关函数
BKP
void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel);//高低电平是否触发TAMPER侵入检测功能
void BKP_TamperPinCmd(FunctionalState NewState);//是否开启TAMPER侵入检测功能
void BKP_ITConfig(FunctionalState NewState);//是否开启中断
void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource);//RTC时钟输出功能配置
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue);//设置RTC校准值
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data);//写备份寄存器
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR);//读备份寄存器
FlagStatus BKP_GetFlagStatus(void);
void BKP_ClearFlag(void);
ITStatus BKP_GetITStatus(void);
void BKP_ClearITPendingBit(void);
PWR
void PWR_BackupAccessCmd(FunctionalState NewState);//备份寄存器使能,设置DBP
rcc.h
void RCC_LSEConfig(uint8_t RCC_LSE);//配置LSE外部低速时钟
void RCC_LSICmd(FunctionalState NewState);//配置LSI内部低速时钟
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);//选择时钟源
void RCC_RTCCLKCmd(FunctionalState NewState);//使能
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);//LSE启动标志位
rtc.h
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);
void RTC_EnterConfigMode(void);//进入配置模式,设置CNF位
void RTC_ExitConfigMode(void);//退出配置模式,将CNF位清零
uint32_t RTC_GetCounter(void);//获取CNT计数器值
void RTC_SetCounter(uint32_t CounterValue);//写入CNT计数器值
void RTC_SetPrescaler(uint32_t PrescalerValue);//写入预分频器(PRL)
void RTC_SetAlarm(uint32_t AlarmValue);//写入闹钟值
uint32_t RTC_GetDivider(void);//读取预分频器中的DIV余数寄存器,可以获取比秒更加精确的时间
void RTC_WaitForLastTask(void);//等待上次操作的完成,等待RTOFF为1
void RTC_WaitForSynchro(void);//等待同步,RSF为1
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
void RTC_ClearFlag(uint16_t RTC_FLAG);
ITStatus RTC_GetITStatus(uint16_t RTC_IT);
void RTC_ClearITPendingBit(uint16_t RTC_IT);
六.代码实现
(1)读写备份寄存器
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
uint16_t ArrayWrite[] = {0x1234,0x5678};
uint16_t ArrayRead[2];
uint8_t Num;
int main(void)
{
OLED_Init();
Key_Init();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
PWR_BackupAccessCmd(ENABLE);
OLED_ShowString(1,1,"W:");
OLED_ShowString(2,1,"R:");
while(1)
{
Num = Keynum();
if(Num == 1)
{
ArrayWrite[0]++;
ArrayWrite[1]++;
BKP_WriteBackupRegister(BKP_DR1,ArrayWrite[0]);
BKP_WriteBackupRegister(BKP_DR2,ArrayWrite[1]);
OLED_ShowHexNum(1,3,ArrayWrite[0],4);
OLED_ShowHexNum(1,8,ArrayWrite[1],4);
ArrayRead[0] = BKP_ReadBackupRegister(BKP_DR1);
ArrayRead[1] = BKP_ReadBackupRegister(BKP_DR2);
}
OLED_ShowHexNum(2,3,ArrayRead[0],4);
OLED_ShowHexNum(2,8,ArrayRead[1],4);
}
}
(2)实时时钟
MyRTC.c
#include "stm32f10x.h" // Device header
#include <time.h>
uint16_t Mytime[6] = {2024,2,20,23,59,55};
void MyRTC_SET(void);
void MyRTC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
PWR_BackupAccessCmd(ENABLE);
if(BKP_ReadBackupRegister(BKP_DR1) != 0x12)
{
RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//需要选择LSE时钟
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
RTC_SetPrescaler(32768 - 1);
RTC_WaitForLastTask();
MyRTC_SET();
BKP_WriteBackupRegister(BKP_DR1,0x12);
}
else
{
RTC_WaitForLastTask();
RTC_WaitForSynchro();
}
}
void MyRTC_SET(void)//输入北京时间,转化为伦敦时间
{
time_t time_cnt;
struct tm time_st;
time_st.tm_year =Mytime[0]-1900;
time_st.tm_mon =Mytime[1]-1;
time_st.tm_mday = Mytime[2];
time_st.tm_hour =Mytime[3];
time_st.tm_min = Mytime[4];
time_st.tm_sec =Mytime[5] ;
time_cnt = mktime(&time_st) - 8*60*60;
RTC_SetCounter(time_cnt);
RTC_WaitForLastTask();
}
void MyRTC_READ(void)//读取伦敦时间,转换为北京时间
{
time_t time_cnt;
struct tm time_st;
time_cnt = RTC_GetCounter() + 8*60*60;
time_st = *localtime(&time_cnt);
Mytime[0]=time_st.tm_year+1900;
Mytime[1]=time_st.tm_mon+1;
Mytime[2]=time_st.tm_mday;
Mytime[3]=time_st.tm_hour;
Mytime[4]=time_st.tm_min;
Mytime[5]=time_st.tm_sec;
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"
int main(void)
{
OLED_Init();
MyRTC_Init();
OLED_ShowString(1,1," - - ");
OLED_ShowString(2,1," : : ");
OLED_ShowString(3,1,"CNT:");
OLED_ShowString(4,1,"DIV:");
while(1)
{
MyRTC_READ();
OLED_ShowNum(1,1,Mytime[0],4);
OLED_ShowNum(1,6,Mytime[1],2);
OLED_ShowNum(1,10,Mytime[2],2);
OLED_ShowNum(2,1,Mytime[3],2);
OLED_ShowNum(2,4,Mytime[4],2);
OLED_ShowNum(2,7,Mytime[5],2);
OLED_ShowNum(3,5,RTC_GetCounter(),10);
OLED_ShowNum(4,5,(32767-RTC_GetDivider())/32767.0*999,10);//需要加上小数点
//可以读取DIV,对其进行线性变换,读取任意时刻的毫秒
}
}