STM32 RTC時鐘帶中文注釋
#include "stm32f10x.h" // Device header
#include <time.h>
uint16_t MyRTC_Time[] = {2024, 2, 26, 15, 18, 00}; //定義全局的時間數組,數組內容分別為年、月、日、時、分、秒
void MyRTC_SetTime(void); //函數聲明
/**
* 函 數:RTC初始化
* 參 數:無
* 返 回 值:無
*/
void MyRTC_Init(void)
{
/*開啟時鐘*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //開啟PWR的時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE); //開啟BKP的時鐘
/*備份寄存器訪問使能*/
PWR_BackupAccessCmd(ENABLE); //使用PWR開啟對備份寄存器的訪問
if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) //通過寫入備份寄存器的標志位,判斷RTC是否是第一次配置
//if成立則執行第一次的RTC配置
{
RCC_LSEConfig(RCC_LSE_ON); //開啟LSE時鐘
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET); //等待LSE準備就緒
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //選擇RTCCLK來源為LSE
RCC_RTCCLKCmd(ENABLE); //RTCCLK使能
RTC_WaitForSynchro(); //等待同步
RTC_WaitForLastTask(); //等待上一次操作完成
RTC_SetPrescaler(32768 - 1); //設置RTC預分頻器,預分頻后的計數頻率為1Hz
RTC_WaitForLastTask(); //等待上一次操作完成
MyRTC_SetTime(); //設置時間,調用此函數,全局數組里時間值刷新到RTC硬件電路
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); //在備份寄存器寫入自己規定的標志位,用于判斷RTC是不是第一次執行配置
}
else //RTC不是第一次配置
{
RTC_WaitForSynchro(); //等待同步
RTC_WaitForLastTask(); //等待上一次操作完成
}
}
//如果LSE無法起振導致程序卡死在初始化函數中
//可將初始化函數替換為下述代碼,使用LSI當作RTCCLK
//LSI無法由備用電源供電,故主電源掉電時,RTC走時會暫停
/*
void MyRTC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
{
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_SetPrescaler(40000 - 1);
RTC_WaitForLastTask();
MyRTC_SetTime();
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
}
else
{
RCC_LSICmd(ENABLE); //即使不是第一次配置,也需要再次開啟LSI時鐘
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
}
}*/
/**
* 函 數:RTC設置時間
* 參 數:無
* 返 回 值:無
* 說 明:調用此函數后,全局數組里時間值將刷新到RTC硬件電路
*/
void MyRTC_SetTime(void)
{
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; //調用mktime函數,將日期時間轉換為秒計數器格式
//- 8 * 60 * 60為東八區的時區調整
RTC_SetCounter(time_cnt); //將秒計數器寫入到RTC的CNT中
RTC_WaitForLastTask(); //等待上一次操作完成
}
/**
* 函 數:RTC讀取時間
* 參 數:無
* 返 回 值:無
* 說 明:調用此函數后,RTC硬件電路里時間值將刷新到全局數組
*/
void MyRTC_ReadTime(void)
{
time_t time_cnt; //定義秒計數器數據類型
struct tm time_date; //定義日期時間數據類型
time_cnt = RTC_GetCounter() + 8 * 60 * 60; //讀取RTC的CNT,獲取當前的秒計數器
//+ 8 * 60 * 60為東八區的時區調整
time_date = *localtime(&time_cnt); //使用localtime函數,將秒計數器轉換為日期時間格式
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;
}
#include "MyRTC.h"
int main(void)
{
/*模塊初始化*/
OLED_Init(); //OLED初始化
MyRTC_Init(); //RTC初始化
// MyRTC_SetTime();//設置時間
/*顯示靜態字符串*/
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(); //RTC讀取時間,最新的時間存儲到MyRTC_Time數組中
OLED_ShowNum(1, 6, MyRTC_Time[0], 4); //顯示MyRTC_Time數組中的時間值,年
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); //顯示32位的秒計數器
OLED_ShowNum(4, 6, RTC_GetDivider(), 10); //顯示余數寄存器
}
}
原理圖: 無
仿真: 無
代碼:
12-2 實時時鐘.7z
(179.82 KB, 下載次數: 23)
2024-2-29 02:51 上傳
點擊文件名下載附件
RTC時鐘 下載積分: 黑幣 -5
|