文章目录
读写备份寄存器
接线图
即接个3.3v的电源到VBT引脚
代码
代码效果:第一次写入备份寄存器,下载程序后再注释掉,再进行下载,之前写入的数据还会保存在备份寄存器中(还可以读到),并且复位键或拔掉主电源再插上数据也不会丢失,直到主电源备用电源同时不能供电数据才会消失
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
uint16_t Data;
int main(void)
{
OLED_Init();
OLED_ShowChar(1,1,'z');
// 打开PWR,BKP时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
// 使能PWR
PWR_BackupAccessCmd(ENABLE);
// 写备份寄存器
//BKP_WriteBackupRegister(BKP_DR1,0X1234);
// 读取备份寄存器
Data = BKP_ReadBackupRegister(BKP_DR1);
OLED_ShowHexNum(2,1,Data,4);
while (1)
{
}
}
RTC实时时钟
接线图
代码
对RTC进行配置,保存于ThisRTC.c
c
#include "stm32f10x.h" // Device header
#include <time.h>
struct ThisRTC_Time{
uint16_t year; // 年
uint8_t month; // 月
uint8_t day; // 日
uint8_t hour; // 时
uint8_t min; // 分
uint8_t sec; // 秒
};
extern struct ThisRTC_Time ThisRTC_Time1;
void ThisRTC_Init(void){
// 打开PWR,BKP时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);
// 使能PWR
PWR_BackupAccessCmd(ENABLE);
// 如果备份寄存器数据丢失则重新初始化
if(BKP_ReadBackupRegister(BKP_DR1) != 0X9999){
// 启动LSE时钟源
RCC_LSEConfig(RCC_LSE_ON);
// 等待LSE启动完成
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=SET);
// 选择RTC时钟源为LSE
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
// 使能RTC时钟
RCC_RTCCLKCmd(ENABLE);
// 等待同步
RTC_WaitForSynchro();
// 等待上一步写操作完成
RTC_WaitForLastTask();
// 配置分频系数,自动进入配置模式并退出
RTC_SetPrescaler(32768-1);
// 等待上一步写操作完成
RTC_WaitForLastTask();
void ThisRTC_SetTime(void);
ThisRTC_SetTime();
// 写入备份寄存器
BKP_WriteBackupRegister(BKP_DR1,0X9999);
}else{
// 等待同步
RTC_WaitForSynchro();
// 等待上一步写操作完成
RTC_WaitForLastTask();
}
}
void ThisRTC_SetTime(void){
time_t time_cnt;
struct tm time_date;
time_date.tm_year = ThisRTC_Time1.year - 1900;
time_date.tm_mon = ThisRTC_Time1.month - 1;
time_date.tm_mday = ThisRTC_Time1.day;
time_date.tm_hour = ThisRTC_Time1.hour;
time_date.tm_min = ThisRTC_Time1.min;
time_date.tm_sec = ThisRTC_Time1.sec;
// 将日期类型转换为秒计数器类型,并设置为RTC时间
time_cnt = mktime(&time_date) - 8 * 60 * 60;
RTC_SetCounter(time_cnt);
// 等待上一步写操作完成
RTC_WaitForLastTask();
}
void ThisRTC_ReadTime(void){
time_t time_cnt;
struct tm time_date;
time_cnt = RTC_GetCounter() + 8 * 60 * 60; // 加时区偏移变为北京时间
time_date = *localtime(&time_cnt);
ThisRTC_Time1.year = time_date.tm_year + 1900;
ThisRTC_Time1.month = time_date.tm_mon + 1;
ThisRTC_Time1.day = time_date.tm_mday;
ThisRTC_Time1.hour = time_date.tm_hour;
ThisRTC_Time1.min = time_date.tm_min;
ThisRTC_Time1.sec = time_date.tm_sec;
}
头文件ThisRTC.h声明
c
#ifndef __THISRTC_H
#define __THISRTC_H
// 存放时间结构体
struct ThisRTC_Time{
uint16_t year; // 年
uint8_t month; // 月
uint8_t day; // 日
uint8_t hour; // 时
uint8_t min; // 分
uint8_t sec; // 秒
};
struct ThisRTC_Time ThisRTC_Time1 = {2024,10,27,5,2,0};
void ThisRTC_Init(void);
void ThisRTC_SetTime(void);
void ThisRTC_ReadTime(void);
#endif
主函数内容
c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "ThisRTC.h"
int main(void)
{
OLED_Init();
ThisRTC_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)
{
ThisRTC_ReadTime();
OLED_ShowNum(1,6,ThisRTC_Time1.year,4);
OLED_ShowNum(1,11,ThisRTC_Time1.month,2);
OLED_ShowNum(1,14,ThisRTC_Time1.day,2);
OLED_ShowNum(2,6,ThisRTC_Time1.hour,2);
OLED_ShowNum(2,9,ThisRTC_Time1.min,2);
OLED_ShowNum(2,12,ThisRTC_Time1.sec,2);
OLED_ShowNum(3,6,RTC_GetCounter(),10);
OLED_ShowNum(4,6,RTC_GetDivider(),6); // 余数寄存器
}
}