STM32 HAL庫RTC實時時鐘超細詳解

一、引言

在嵌入式系統的應用中,實時時鐘(RTC)是一個非常重要的功能模塊。它能夠獨立于主系統提供精確的時間和日期信息,即使在系統斷電的情況下,也可以依靠備用電池繼續運行。STM32F407 是一款性能強大的微控制器,其內置的 RTC 外設結合 HAL 庫,為開發者提供了便捷、高效的實時時鐘解決方案。本文將詳細介紹基于 STM32F407 HAL 庫的 RTC 實時時鐘的開發過程,包括硬件連接、時鐘配置、時間設置與讀取等方面的內容。

二、STM32F407 RTC 硬件特性

2.1 RTC 基本結構

STM32F407 的 RTC 外設主要由以下幾個部分組成:

  • 時鐘源:RTC 可以使用三種不同的時鐘源,分別是低速內部時鐘(LSI,約 32kHz)、低速外部時鐘(LSE,32.768kHz)和高速外部時鐘(HSE)經過 128 分頻后的時鐘。其中,LSE 由于其高精度和穩定性,是 RTC 最常用的時鐘源。
  • 預分頻器:用于將時鐘源的頻率進行分頻,以得到合適的 RTC 時鐘頻率。預分頻器分為兩個部分,一個是異步預分頻器(PSC),另一個是同步預分頻器(SYNCH_PREDIV)。
  • 計數器:RTC 包含兩個 32 位的計數器,分別是秒計數器(RTC_SSR)和日歷計數器(RTC_TR 和 RTC_DR)。秒計數器用于記錄秒數,日歷計數器用于記錄時間和日期信息。
  • 鬧鐘寄存器:RTC 提供了兩個鬧鐘寄存器(RTC_ALRMAR 和 RTC_ALRMBR),可以設置鬧鐘時間,當達到設定的鬧鐘時間時,會產生鬧鐘中斷。

2.2 備用電源

為了保證 RTC 在系統斷電的情況下仍然能夠正常運行,需要為其提供備用電源。STM32F407 的 RTC 可以通過 VBAT 引腳連接備用電池,當主電源 VDD 斷電時,備用電池會自動為 RTC 供電。

三、開發環境搭建

3.1 硬件準備

  • STM32F407 開發板:選擇一款合適的 STM32F407 開發板,如正點原子的探索者開發板或野火的指南者開發板。
  • 調試工具:使用 ST-Link 或 J-Link 調試器,用于將程序下載到開發板上。
  • 備用電池:選擇合適的紐扣電池,如 CR1220,連接到開發板的 VBAT 引腳。

3.2 軟件準備

  • 開發工具:使用 Keil MDK-ARM 集成開發環境,該環境支持 STM32 系列微控制器的開發。
  • STM32CubeMX:用于快速配置 STM32 的外設和生成初始化代碼。STM32CubeMX 是一款圖形化的配置工具,它可以幫助開發者快速生成基于 HAL 庫的初始化代碼,大大提高開發效率。

四、基于 HAL 庫的 RTC 編程

4.1 代碼結構分析

使用 STM32CubeMX 生成的代碼包含了 RTC 的初始化代碼,主要在main.cstm32f4xx_hal_msp.c文件中。在main.c文件中,會調用MX_RTC_Init()函數來初始化 RTC 外設。

/* USER CODE BEGIN PFP */
/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_RTC_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

4.2 時間設置

在程序中,可以使用HAL_RTC_SetTime()HAL_RTC_SetDate()函數來設置 RTC 的時間和日期。以下是一個設置時間和日期的示例代碼:

#include "main.h"
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef hrtc;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef sDate = {0};// 設置時間為12:30:00sTime.Hours = 12;sTime.Minutes = 30;sTime.Seconds = 0;HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);// 設置日期為2024年10月1日sDate.Year = 24;sDate.Month = RTC_MONTH_OCTOBER;sDate.Date = 1;HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);while (1){// 主循環}
}

4.3 時間讀取

使用HAL_RTC_GetTime()HAL_RTC_GetDate()函數可以讀取 RTC 的當前時間和日期。以下是一個讀取時間和日期并通過串口輸出的示例代碼:

#include "main.h"
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART1_UART_Init();RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef sDate = {0};char buffer[50];while (1){HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);sprintf(buffer, "Date: %02d/%02d/%02d Time: %02d:%02d:%02d\r\n",sDate.Date, sDate.Month, 2000 + sDate.Year,sTime.Hours, sTime.Minutes, sTime.Seconds);HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);HAL_Delay(1000);}
}

4.4 鬧鐘設置與中斷處理

RTC 可以設置鬧鐘功能,當達到設定的鬧鐘時間時,會產生鬧鐘中斷。以下是一個設置鬧鐘并處理中斷的示例代碼:

#include "main.h"
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{char buffer[] = "Alarm triggered!\r\n";HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART1_UART_Init();RTC_AlarmTypeDef sAlarm = {0};// 設置鬧鐘時間為12:31:00sAlarm.AlarmTime.Hours = 12;sAlarm.AlarmTime.Minutes = 31;sAlarm.AlarmTime.Seconds = 0;sAlarm.Alarm = RTC_ALARM_A;HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);while (1){// 主循環}
}

五、RTC 校準

由于時鐘源存在一定的誤差,長時間運行后 RTC 的時間可能會出現偏差。為了提高 RTC 的時間精度,可以對其進行校準。STM32F407 的 RTC 提供了校準功能,可以通過設置校準寄存器(RTC_CALR)來調整時鐘頻率。

5.1 校準原理

RTC 的校準功能是通過在每 256 秒內插入或刪除一個時鐘脈沖來實現的。校準寄存器(RTC_CALR)的低 7 位(CAL [6:0])用于設置校準值,CAL [6] 為校準方向位,0 表示插入脈沖,1 表示刪除脈沖。

5.2 校準代碼示例

void RTC_Calibration(int calibration_value)
{// 檢查校準值是否在有效范圍內if (calibration_value >= -64 && calibration_value <= 63){uint32_t calr_value = 0;if (calibration_value < 0){calr_value |= (1 << 6); // 設置校準方向為刪除脈沖calibration_value = -calibration_value;}calr_value |= (calibration_value & 0x3F);HAL_RTCEx_SetCalibrationValue(&hrtc, calr_value);}
}

六、RTC 低功耗模式

在一些對功耗要求較高的應用中,需要將 STM32F407 設置為低功耗模式,同時保證 RTC 正常運行。STM32F407 提供了多種低功耗模式,如睡眠模式、停止模式和待機模式。

6.1 停止模式

停止模式是一種低功耗模式,在該模式下,系統時鐘停止運行,但 RTC、備份寄存器和待機電路仍然工作。以下是一個進入停止模式并在鬧鐘中斷喚醒的示例代碼:

#include "main.h"
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{char buffer[] = "Wake up from Stop mode!\r\n";HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);// 重新配置系統時鐘SystemClock_Config();
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART1_UART_Init();RTC_AlarmTypeDef sAlarm = {0};// 設置鬧鐘時間為12:32:00sAlarm.AlarmTime.Hours = 12;sAlarm.AlarmTime.Minutes = 32;sAlarm.AlarmTime.Seconds = 0;sAlarm.Alarm = RTC_ALARM_A;HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);while (1){// 進入停止模式HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);}
}

6.2 待機模式

待機模式是一種功耗最低的模式,在該模式下,所有的寄存器和 SRAM 內容都會被保留,但系統會完全停止運行。RTC 可以作為喚醒源,當鬧鐘時間到達時,系統會從待機模式中喚醒。以下是一個進入待機模式并在鬧鐘中斷喚醒的示例代碼:

#include "main.h"
#include "rtc.h"
#include "stdio.h"RTC_HandleTypeDef hrtc;
UART_HandleTypeDef huart1;void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{char buffer[] = "Wake up from Standby mode!\r\n";HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);// 重新初始化所有外設HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART1_UART_Init();
}int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_RTC_Init();MX_USART1_UART_Init();RTC_AlarmTypeDef sAlarm = {0};// 設置鬧鐘時間為12:33:00sAlarm.AlarmTime.Hours = 12;sAlarm.AlarmTime.Minutes = 33;sAlarm.AlarmTime.Seconds = 0;sAlarm.Alarm = RTC_ALARM_A;HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);while (1){// 進入待機模式HAL_PWR_EnterSTANDBYMode();}
}

七、常見問題與解決方案

7.1 RTC 時間不準確

  • 原因:時鐘源不穩定、溫度影響、校準值設置不當等。
  • 解決方案:選擇穩定的時鐘源(如 LSE),對 RTC 進行校準,盡量減少溫度對時鐘源的影響。

7.2 RTC 在斷電后時間丟失

  • 原因:備用電池沒電、VBAT 引腳連接不良等。
  • 解決方案:更換備用電池,檢查 VBAT 引腳的連接是否正常。

7.3 鬧鐘中斷不觸發

  • 原因:鬧鐘時間設置錯誤、中斷使能位未設置、中斷優先級設置不當等。
  • 解決方案:檢查鬧鐘時間設置是否正確,確保中斷使能位已設置,調整中斷優先級。

八、總結

本文詳細介紹了基于 STM32F407 HAL 庫的 RTC 實時時鐘的開發過程,包括硬件特性、開發環境搭建、基于 HAL 庫的編程、校準、低功耗模式以及常見問題與解決方案等方面的內容。通過本文的學習,讀者可以全面掌握 STM32F407 RTC 的開發方法,為開發具有實時時鐘功能的嵌入式系統打下堅實的基礎。在實際應用中,開發者可以根據具體需求對 RTC 進行靈活配置和使用,以滿足不同的應用場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901272.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901272.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901272.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vdso概念及原理,vdso_fault缺頁異常,vdso符號的獲取

一、背景 vdso的全稱是Virtual Dynamic Shared Object&#xff0c;它是一個特殊的共享庫&#xff0c;是在編譯內核時生成&#xff0c;并在內核鏡像里某一段地址段作為該共享庫的內容。vdso的前身是vsyscall&#xff0c;為了兼容一些舊的程序&#xff0c;x86上還是默認加載了vs…

Linux中的文件傳輸(附加詳細實驗案例)

一、實驗環境的設置 ①該實驗需要兩臺主機&#xff0c;虛擬機名稱為 L2 和 L3 &#xff0c;在終端分別更改主機名為 node1 和 node2&#xff0c;在實驗過程能夠更好分辨。 然后再重新打開終端&#xff0c;主機名便都更改了相應的名稱。 ②用 ip a 的命令分別查看兩個主機的 …

【從0到1學Elasticsearch】Elasticsearch從入門到精通(上)

黑馬商城作為一個電商項目&#xff0c;商品的搜索肯定是訪問頻率最高的頁面之一。目前搜索功能是基于數據庫的模糊搜索來實現的&#xff0c;存在很多問題。 首先&#xff0c;查詢效率較低。 由于數據庫模糊查詢不走索引&#xff0c;在數據量較大的時候&#xff0c;查詢性能很差…

圖論基礎理論

在我看來&#xff0c;想要掌握圖的基礎應用&#xff0c;僅需要三步走。 什么是圖&#xff08;基本概念&#xff09;、圖的構造&#xff08;打地基&#xff09;、圖的遍歷方式&#xff08;應用的基礎&#xff09; 只要能OK的掌握這三步、就算圖論入門了&#xff01;&#xff0…

詳細解讀react框架中的hooks

React Hooks 是 React 16.8 引入的一項革命性特性&#xff0c;它允許你在函數組件中使用狀態(state)和其他 React 特性&#xff0c;而無需編寫 class 組件。下面將詳細解讀 React Hooks 的核心概念、常用 Hooks 及其工作原理。 一、Hooks 的核心概念 1. 什么是 Hooks Hooks …

主機IP動態變化時如何通過固定host.docker.internal訪問本機服務

場景需求——主機IP動態變化時&#xff0c;通過固定的 http://host.docker.internal:11555 訪問本機服務&#xff0c;核心問題在于 host.docker.internal 的解析邏輯與動態IP的適配。以下是分步解決方案&#xff1a; 一、核心原理&#xff1a;host.docker.internal 的本質與局…

插值算法 - 最近鄰插值實現

目錄 1. 導入必要的庫 2. nearest_neighbor_interpolation 3. 測試代碼 數學原理 完整代碼 本文實現了基于最近鄰插值算法的圖像縮放功能。 它使用 Python 編寫,主要依賴于NumPy和PIL(Python Imaging Library)庫。 NumPy用于高效的數值計算,而PIL僅用于圖像的加載和…

windows中搭建Ubuntu子系統

windows中搭建虛擬環境 1.配置2.windows中搭建Ubuntu子系統2.1windows配置2.1.1 確認啟用私有化2.1.2 將wsl2設置為默認版本2.1.3 確認開啟相關配置2.1.4重啟windows以加載更改配置 2.2 搭建Ubuntu子系統2.2.1 下載Ubuntu2.2.2 遷移位置 3.Ubuntu子系統搭建docker環境3.1安裝do…

MySQL事務機制

目錄 原子性 持久性 隔離性 隔離級別(并發事務之間的關系) 讀未提交 讀已提交 可重復讀 串行化(最嚴格的隔離級別) 一致性 問題 不可重復讀性(已經提交的數據) 什么是臟讀問題(未提交的數據)? 幻讀 保存點 自動提交機制--autocommit 會話隔離級別與全局隔離級…

Cadence學習筆記之---直插元件的封裝制作

目錄 01 | 引 言 02 | 環境描述 03 | 操作步驟 04 | 結 語 01 | 引 言 在之前發布的Cadence小記中&#xff0c;已經講述了怎樣制作熱風焊盤&#xff0c;貼片(SMD)焊盤、通孔、過孔&#xff0c;以及貼片元件的封裝。 本篇關于Cadence的小記主要講如何制作直插元件的封裝。 …

【第四十周】文獻閱讀:用于檢索-增強大語言模型的查詢與重寫

目錄 摘要Abstract用于檢索-增強大語言模型的查詢與重寫研究背景方法論基于凍結LLM的重寫方案基于可訓練重寫器的方案重寫器預熱訓練&#xff08;Rewriter Warm-up&#xff09;強化學習&#xff08;Reinforcement Learning&#xff09; 創新性實驗結果局限性總結 摘要 這篇論文…

java學習總結(if switch for)

一.基本結構 1.單分支if int num 10; if (num > 5) {System.out.println("num 大于 5"); } 2.雙分支if-else int score 60; if (score > 60) {System.out.println("及格"); } else {System.out.println("不及格"); } 3.多分支 int…

yum的基本操作和vim指令

在我們的手機端或者Windows上下載軟件&#xff0c;可以在相應的應用商店或者官網進行下載&#xff0c;這樣對于用戶來說十分的方便和便捷。而在Linux上&#xff0c;也有類似的安裝方式&#xff0c;我們來一一了解一下。 Linux安裝軟件的3種方法 源代碼安裝 在Linux下安裝軟件…

C++ CUDA開發入門

CUDA開發筆記 文章目錄 CUDA開發筆記[toc]1 概述2 環境3 命令行編譯4 CMAKE引入CUDA5 vscode開發CUDA6 Qt中使用CUDA-CMake7 QMake配置CUDA8 核函數9 核函數調用9.1 核函數調用語法9.2 執行配置參數詳解9.3 關鍵調用步驟9.4 重要注意事項9.5 調用示例分析9.6 最佳實踐建議 10 線…

llm開發框架新秀

原文鏈接:https://i68.ltd/notes/posts/20250404-llm-framework3/ google開源ADK-Agent Development Kit 開源的、代碼優先的 Python 工具包&#xff0c;用于構建、評估和部署具有靈活性和控制力的復雜智能體項目倉庫:https://github.com/google/adk-python 2.6k項目文檔:Age…

VM——相機拍照失敗

1、問題&#xff1a;相機頻閃觸發&#xff0c;在MVS中正常出圖&#xff0c;在VM中出現拍照失敗 2、解決&#xff1a; 1、首先排查網絡設置&#xff08;巨幀是否設置&#xff09; 2、電腦的所有防火墻是否關閉 3、在MVS中恢復相機的設置參數為默認參數&#xff0c;刪除VM中的全…

【時頻譜分析】小波分析

算法配置頁面&#xff0c;也可以一鍵導出結果數據 報表自定義繪制 獲取和下載【PHM學習軟件PHM源碼】的方式 獲取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc

怎么免費下載GLTF/GLB格式模型文件,還可以在線編輯修改

? 現在非常流行glb格式模型&#xff0c;和gltf格式文件&#xff0c;可是之類模型網站非常非常少 1&#xff0c;咱們先直接打開http://glbxz.com 官方glb下載網站 glbxz.com 2 可以搜索&#xff0c;自己想要的模型關鍵詞 3&#xff0c;到自己想下載素材頁面 4&#xff0c;…

【6】深入學習http模塊(萬字)-Nodejs開發入門

深入學習http模塊 前言http一個Web服務器項目創建代碼運行代碼解析 Server屬性&#xff1a;keepAlive屬性&#xff1a;keepAliveTimeout屬性&#xff1a;maxHeaderSize屬性&#xff1a;requestTimeout屬性&#xff1a;maxRequestsPerSocket方法&#xff1a;close()方法&#xf…

buuctf sql注入類練習

BUU SQL COURSE 1 1 實例無法訪問 / Instance cant be reached at that time | BUUCTF但是這個地方很迷惑就是這個 一個 # 我們不抓包就不知道這個是sql注入類的判斷是 get 類型的sql注入直接使用sqlmap我們放入到1.txt中 目的是 優先檢測 ?id1>python3 sqlmap.py -r 1.t…