12:STM32---RTC real-time clock

Table of contents

1: Time related

1:Unix timestamp

2: UTC/GMT

3: Timestamp conversion

2:BKP

1: Resume

2:Basic structure

Three: RTC

1: Resume

2: Block diagram

3:RTC basic structure

4: Notes on RTC operation

Four: Case

A: Read and write backup register

1: Connection diagram

2: Steps

 3: code 

B: real-time clock

1: Connection diagram

2: Function introduction 

3: Code


1: Time related

1:Unix timestamp

        Unix Timestamp is defined as the number of seconds that have elapsed since 0:00:00 on January 1, 1970 UTC/GMT, regardless of leap seconds.

        The timestamp is stored in a seconds counter, which is a 32-bit/64-bit integer variable.

        The seconds counter is the same for all time zones in the world. Different time zones add offsets to get the local time.

2: UTC/GMT

         GMT (Greenwich Mean Time) Greenwich Mean Time is a time measurement system based on the rotation of the earth. It divides the time interval of one rotation of the earth into 24 hours to determine the timing standard.

         UTC (Universal Time Coordinated) is a time measurement system based on atomic clocks. It stipulates that the duration of 9,192,631,770 cycles of transition radiation between the two hyperfine energy levels of the ground state of a cesium 133 atom in a zero magnetic field is 1 second. When the difference between the atomic clock's day time and the Earth's rotation time exceeds 0.9 seconds, UTC will perform a leap second to ensure that its timing is consistent with the Earth's rotation.

3: Timestamp conversion

        The time.h module of C language provides related functions for time acquisition and timestamp conversion, which can easily convert between seconds counter, date and time and string.

2:BKP

1: Resume

        BKP (Backup Registers) backup registers

        BKP can be used to store user application data. When the VDD (2.0~3.6V) power supply is cut off, they are still powered by VBAT (1.8~3.6V). They are also not reset when the system wakes up from standby mode, or when a system reset or power reset occurs

        A trespass event generated by the TAMPER pin clears all backup register contents.

        The RTC pin outputs RTC calibration clock, RTC alarm pulse or second pulse

        Store RTC clock calibration register user data storage capacity:     

                20 bytes (medium capacity and small capacity) / 84 bytes (large capacity and interconnection type)

2:Basic structure

        BKP is in the backup area, and the role of the backup area: when the VDD main power supply is powered off, the backup area can still be powered by the VBAT backup battery; when the VDD main power supply is powered on, the backup area power supply will be switched from VBAT to VDD, that is, the main When the power supply is powered on, VBAT will not be used, thus saving battery power.

        The BKP mainly includes: data register, control register, status register and RTC clock calibration register. The data register is the main part and is used to store data. Each data odd register is 16 bits. One data odd register can Store 2 bytes. For the small ones, there are DR1, DR2, up to, and DR10, a total of 10 data registers; for the large-capacity and interconnected types, there are DR11~DR42 data registers.

        A detection annunciator can be introduced from the TAMPERS pin at PC13. When TAMPER generates a rising edge or a falling edge, all contents of the BKP will be cleared to ensure safety -----corresponding to the third item in the resume

        Clock output, the RTC related clock can be output from the RTC pin at PC13 for external use. When the calibration clock is output, the error of the RTC can be calibrated with this calibration register.

Three: RTC

1: Resume

        RTC (Real Time Clock) real-time clock

        RTC is an independent timer that can provide clock and calendar functions for the system. The RTC and clock configuration system are in the backup area. The data is not cleared when the system is reset. After VDD (2.0~3.6V) is powered off, VBAT (1.8~ 3.6V) power supply continues to run

        32-bit programmable counter, second counter that can correspond to Unix timestamp

        20-bit programmable prescaler can adapt to input clocks of different frequencies

        Three RTC clock sources can be selected:     

                HSE clock divided by 128 (usually 8MHz/128)     

                LSE oscillator clock (typically 32.768KHz)     

                LSI oscillator clock (40KHz)

2: Block diagram

3:RTC basic structure

        There are 3 clocks, choose one as RTCCLK, and then RTCCLK first passes through the prescaler to divide the clock.

        Remainder register (DIV): It is a self-decreasing counter that stores the current count value.

        Reload register: It is the counting target and determines the frequency division value. After division, a 1Hz second counting signal is obtained, which leads to a 32-bit counter that increments once a second.

        Three signals can trigger interrupts, namely the second signal, the counter overflow signal and the alarm signal. The three signals are first controlled by the interrupt output. The three signals are first controlled by the interrupt output. Only the enabled interrupt can be directed to the NVIC.

4: Notes on RTC operation

        Doing the following will enable access to BKP and RTC:   

                 Set PWREN and BKPEN of RCC_APB1ENR and enable PWR and BKP clocks     

                Set the DBP of PWR_CR to enable access to BKP and RTC

        If the RTC's APB1 interface has been disabled when reading the RTC register, the software must first wait for the RSF bit (register synchronization flag) in the RTC_CRL register to be set to 1 by hardware.

        The CNF bit in the RTC_CRL register must be set so that the RTC can enter the configuration mode before writing to the RTC_PRL, RTC_CNT, and RTC_ALR registers. In fact, this operation is in the library function. Each function that writes odd registers, It automatically adds this operation for us, so we don’t need to call the code separately to enter the configuration mode.

        A write operation to any RTC register must be performed after the previous write operation is completed. You can determine whether the RTC register is being updated by querying the RTOFF status bit in the RTC_CR register. Writing to the RTC register is only possible when the RTOFF status bit is 1

Four: Case

A: Read and write backup register

1: Connection diagram

2: Steps

  1: Set PWREN and BKPEN of RCC_APB1ENR and enable PWR and BKP clocks     

  2: Set the DBP of PWR_CR to enable access to BKP and RTC

 3: code 

Simple implementation of BKP functions 

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"

void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

uint8_t Key_GetNum(void)
{
	uint8_t KeyNum = 0;
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
		Delay_ms(20);
		KeyNum = 1;
	}
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0)
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0);
		Delay_ms(20);
		KeyNum = 2;
	}
	
	return KeyNum;
}


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

        1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     

        2: 设置PWR_CR的DBP,使能对BKP和RTC的访问

*/
uint16_t ArrayWrite[]={0x1234,0x5678};
uint16_t ArrayRead[2];
uint16_t KeyNum;
int main(void)
{	
	Key_Init();
	OLED_Init();
	//1: 设置RCC_APB1ENR的PWREN和BKPEN,使能PWR和BKP时钟     
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	//2: 设置PWR_CR的DBP,使能对BKP和RTC的访问
	PWR_BackupAccessCmd(ENABLE);
	
	OLED_ShowString(1,1,"W:");
	OLED_ShowString(3,1,"R:");
	
	while (1)
	{
		KeyNum=Key_GetNum();
		if (KeyNum==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(3,3,ArrayRead[0],4);
		OLED_ShowHexNum(3,8,ArrayRead[1],4);
	
	}
	
}

 Doing the following will enable access to BKP and RTC:     

        1: Set PWREN and BKPEN of RCC_APB1ENR and enable PWR and BKP clocks     

        2: Set the DBP of PWR_CR to enable access to BKP and RTC

B: real-time clock

1: Connection diagram

2: Function introduction 

In the file stm32f10x_rcc.h ----- clock-related functions

void RCC_LSEConfig(uint8_t RCC_LSE);

void RCC_LSICmd(FunctionalState NewState);

void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
 

void RCC_RTCCLKCmd(FunctionalState NewState)

RCC_LSEConfig : configure external low-speed clock (LSE)

RCC_LSICmd : configure internal low-speed clock (LSI)

RCC_RTCCLKConfig : This function is used to select the clock source of RTCCLK. It is actually the data selector that configures the PPT.

RCC_RTCCLKCmd : Enable--turn on or off the RTC clock

After the clock is selected, it is necessary to obtain the flag bit and wait for the flag to be completed before operating

	RCC_LSEConfig(RCC_LSE_ON);//选择外部低速时钟
	
	while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//LSE准备ok了

In the file stm32f10x_rcc.h -----get the flag bit function

FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG);

In the file stm32f10x_rtc.h -----Enter RTC configuration mode

void RTC_EnterConfigMode(void)

 The function of this function is to set the CNF of CRL to 1 and enter the configuration mode.

        The CNF bit in the RTC_CRL register must be set so that the RTC enters configuration mode before writing to the RTC_PRL, RTC_CNT, and RTC_ALR registers.

In the file stm32f10x_rtc.h -----Exit RTC configuration mode

void RTC_ExitConfigMode(void)

Function: It is to clear the CNF bit 

In the file stm32f10x_rtc.h -----CNT counter related

uint32_t RTC_GetCounter(void)
 

void RTC_SetCounter(uint32_t CounterValue)

RTC_GetCounter : Get RTC counter value

RTC_SetCounter : the value written to CNT

In the file stm32f10x_rtc.h-----prescaler

void RTC_SetPrescaler(uint32_t PrescalerValue)

 RTC_SetPrescaler : Write the value of the prescaler----This value will be written to the PRL reload register of the prescaler and is used to configure the division coefficient of the prescaler

In the file stm32f10x_rtc.h ----- write the value of the alarm clock

void RTC_SetAlarm(uint32_t AlarmValue)

In the file stm32f10x_rtc.h ----- Read the DIV remainder register in the prescaler

 uint32_t  RTC_GetDivider(void);

The remainder odd register is a self-decreasing counter. Obtaining the value of the remainder odd register is generally to obtain a more detailed time.

In the file stm32f10x_rtc.h -----wait for the completion of the operation

void RTC_WaitForLastTask(void);

void RTC_WaitForSynchro(void);

RTC_WaitForLastTask : Wait for the last operation to complete 

        A write operation to any RTC register must be performed after the previous write operation is completed. You can determine whether the RTC register is being updated by querying the RTOFF status bit in the RTC_CR register. Writing to the RTC register is only possible when the RTOFF status bit is 1

 RTC_WaitForSynchro : Wait for synchronization----clear the RSF flag, then loop until RSF is 1

        If the RTC's APB1 interface has been disabled when reading the RTC register, the software must first wait for the RSF bit (register synchronization flag) in the RTC_CRL register to be set to 1 by hardware.

3: Code

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MYRTC.h"

uint16_t MyRTC_Time[] = {2023, 1, 1, 23, 59, 55};
void MYRTC_init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	PWR_BackupAccessCmd(ENABLE);
	
	if(BKP_ReadBackupRegister(BKP_DR1)!=0xA5A5)
	{
		//LSE的频率是32.768KHz,也就是32768Hz
		RCC_LSEConfig(RCC_LSE_ON);//选择外部低速时钟
		
		while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//LSE准备ok了
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//配置RTC时钟RTCCLK
		RCC_RTCCLKCmd(ENABLE);//开启RTC时钟
		
		RTC_WaitForLastTask();//等待上次操作完成 
		RTC_WaitForSynchro();//等待同步时钟
		
		//写预分频器
		RTC_SetPrescaler(32768-1);
		RTC_WaitForLastTask();
		
		RTC_SetCounter(1672588795); //写入CNT
		RTC_WaitForLastTask();
		
		BKP_WriteBackupRegister(BKP_DR1,0xA5A5);
	
	}
	else
	{
			
		RTC_WaitForLastTask();//等待上次操作完成 
		RTC_WaitForSynchro();//等待同步时钟
		
	}

	
}

void MYRTC_Settime(void)
{
	//内部的定义typedef unsigned int time_t; /* date/time in unix secs past 1-Jan-70 */	
	time_t time_cnt;
	struct tm time_date;
	time_date.tm_year = MyRTC_Time[0] - 1900;
	time_date.tm_mon = MyRTC_Time[1] - 1;
	time_date.tm_mday = MyRTC_Time[2];
	time_date.tm_hour = MyRTC_Time[3];
	time_date.tm_min = MyRTC_Time[4];
	time_date.tm_sec = MyRTC_Time[5];
	//默认是伦敦时间,  转化为北京的东八区的时间
	time_cnt=mktime(&time_date)-8*60*60; //mktimer日期类型的时间数据类型--转化为--秒计数器数据类型
	RTC_SetCounter(time_cnt);//写入CNT计数器
	RTC_WaitForLastTask();

}
	
void MyRTC_ReadTime(void)
{
	time_t time_cnt;
	struct tm time_date;
	
	time_cnt = RTC_GetCounter() + 8 * 60 * 60;
	
	time_date = *localtime(&time_cnt);  //秒计数器数据类型--转化为---日期类型的时间数据类型
	
	MyRTC_Time[0] = time_date.tm_year + 1900;
	MyRTC_Time[1] = time_date.tm_mon + 1;
	MyRTC_Time[2] = time_date.tm_mday;
	MyRTC_Time[3] = time_date.tm_hour;
	MyRTC_Time[4] = time_date.tm_min;
	MyRTC_Time[5] = time_date.tm_sec;
}




int main(void)
{
	OLED_Init();
	MYRTC_init();
	
	OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
	OLED_ShowString(2, 1, "Time:XX:XX:XX");
	OLED_ShowString(3, 1, "CNT :");
	OLED_ShowString(4, 1, "DIV :");
	
	while (1)
	{
		MyRTC_ReadTime();
		
		OLED_ShowNum(1, 6, MyRTC_Time[0], 4);
		OLED_ShowNum(1, 11, MyRTC_Time[1], 2);
		OLED_ShowNum(1, 14, MyRTC_Time[2], 2);
		OLED_ShowNum(2, 6, MyRTC_Time[3], 2);
		OLED_ShowNum(2, 9, MyRTC_Time[4], 2);
		OLED_ShowNum(2, 12, MyRTC_Time[5], 2);
		
		OLED_ShowNum(3, 6, RTC_GetCounter(), 10);
		OLED_ShowNum(4, 6, RTC_GetDivider(), 10);
	}
}

Guess you like

Origin blog.csdn.net/m0_74739916/article/details/133084178