單片機外設(七)RTC時間獲取

文章目錄

  • 一.RTC介紹
  • 二.IMX6ull RTC介紹
    • 1.SNVS_HP (high power domain)
    • 2.SNVS_LP (low power domain)
    • 3.SNVS interrupts and alarms
  • 三. SNVS重點寄存器介紹
    • 1.SNVS_HP Command(HPCOMR)
    • 2.SNVS_HP/SNVS_LP Control register (SNVS_HPCR/SNVS_LPCR)
    • 3.SNVS_HP/SNVS_LP 狀態寄存器(SNVS_HPSR/SNVS_LPSR)
    • 4.SNVS_HP/SNVS_LP 實時計數器高字節寄存器(HPRTCMR/LPSRTCMR)
    • 5.SNVS_HP/SNVS_LP 實時計數器低字節寄存器(SNVS_HPRTCLR/SNVS_LPSRTCLR)
    • 6.SNVS_HP 時間報警高字節寄存器(SNVS_HPTAMR)
  • 四.獲取RTC時間
    • 1.編程思路
    • 2.日期時間與秒時間之間轉換
      • (1)daetime.h
      • (2)datetime.c
    • 3.代碼
  • 五.Alarm 中斷
    • 1. 編程思路
      • RTC 鬧鐘功能操作步驟
    • 2.代碼

一.RTC介紹

實時時鐘(Real Time Clock, RTC):可在系統斷電時用備用電池工作,斷電時備用電池能存儲秒、分、小時、周、日、月、年時間數據,單元外接32.768 kHz晶振,有定時報警功能 。

二.IMX6ull RTC介紹

  • 硬件功能:imx6ull芯片的Secure Non - Volatile Storage (SNVS)提供RTC功能 ,其低功耗(電池支持)部分含安全實時計數器、單調計數器、通用寄存器,由電池供電,芯片斷電時電池保持SNVS_LP寄存器狀態 。
  • 專業術語:Secure Non - Volatile Storage (SNVS)(安全非易失性存儲)、RTC(Real Time Clock,實時時鐘 ) 、monotonic counter(單調計數器 ) 、SNVS_LP registers(SNVS低功耗寄存器 ) 。

在這里插入圖片描述

  • SNVS_HP部分功能:實現啟用系統通信和SNVS_LP部分分配配置的所有功能
  • SNVS_LP部分功能:提供能夠安全存儲和保護敏感數據的硬件,其內部有SRTC(定時器 ),核心板為其提供32.768KHz時鐘信號即可工作 。

1.SNVS_HP (high power domain)

  1. 功能單元:SNVS_HP分為IP總線接口、SNVS_LP接口、帶報警功能的實時計數器、控制和狀態寄存器這些功能單元 。
  2. 供電與接口:SNVS_HP位于芯片電源域,與芯片其余部分一同供電;是SNVS_LP和系統其余部分間的接口,訪問SNVS_LP寄存器須經SNVS_HP且其需上電,通過寄存器訪問權限策略決定是否允許訪問特定寄存器 。

2.SNVS_LP (low power domain)

功能單元:SNVS_LP(低功耗域)的功能單元有非翻轉單調計數器、通用寄存器、控制和狀態寄存器 。
子系統與電源:SNVS_LP是數據存儲子系統,用于存儲和保護系統數據,不受主系統電源狀態影響;處于始終上電域,為單獨電源域,有自身電源 。

3.SNVS interrupts and alarms

在這里插入圖片描述

  1. 時間報警寄存器功能
    • SNVS_HP非安全RTC有自身時間報警寄存器,應用程序可更新。
    • 能生成中斷提醒主機處理器,可從低功耗模式喚醒主機處理器;系統斷電時無法喚醒整個系統(因報警也斷電 )。
  2. 周期性中斷功能
    • SNVS_HP非安全RTC含周期性中斷,RTC選定位0 - 1或1 - 0轉換時產生。
    • 中斷源依HP控制寄存器PI_FREQ字段,從HP RTC 16位中選,位選擇定義中斷頻率 。

三. SNVS重點寄存器介紹

1.SNVS_HP Command(HPCOMR)

在這里插入圖片描述

2.SNVS_HP/SNVS_LP Control register (SNVS_HPCR/SNVS_LPCR)

在這里插入圖片描述

3.SNVS_HP/SNVS_LP 狀態寄存器(SNVS_HPSR/SNVS_LPSR)

在這里插入圖片描述

4.SNVS_HP/SNVS_LP 實時計數器高字節寄存器(HPRTCMR/LPSRTCMR)

在這里插入圖片描述

5.SNVS_HP/SNVS_LP 實時計數器低字節寄存器(SNVS_HPRTCLR/SNVS_LPSRTCLR)

在這里插入圖片描述

6.SNVS_HP 時間報警高字節寄存器(SNVS_HPTAMR)

在這里插入圖片描述
在這里插入圖片描述

四.獲取RTC時間

1.編程思路

  • 操作步驟類:
    • 使能SNVS時鐘
    • 設置寄存器訪問不受權限限制
    • 停止RTC計數器,等待RTC計數器停止成功
    • 設置日期
    • 開啟RTC計數器,等待RTC計數器開啟成功
    • 每隔1秒讀取RTC數據,然后輸出

2.日期時間與秒時間之間轉換

(1)daetime.h

#ifndef _DATETIME_HEAD_H
#define _DATETIME_HEAD_H#include <stdint.h>#define SECONDS_IN_A_DAY (86400U)
#define SECONDS_IN_A_HOUR (3600U)
#define SECONDS_IN_A_MINUTE (60U)
#define DAYS_IN_A_YEAR (365U)
#define YEAR_RANGE_START (1970U)
#define YEAR_RANGE_END (2099U)typedef struct rtc_datetime
{uint16_t year;   /*!< Range from 1970 to 2099. */uint8_t month;   /*!< Range from 1 to 12. */uint8_t day;     /*!< Range from 1 to 31 (depending on month). */uint8_t hour;    /*!< Range from 0 to 23. */uint8_t minute;  /*!< Range from 0 to 59. */uint8_t second;  /*!< Range from 0 to 59. */
} rtc_datetime_t;extern uint32_t convert_datetime_to_seconds(const rtc_datetime_t *datetime);
extern void convert_seconds_to_datetime(uint32_t seconds, rtc_datetime_t *datetime);#endif /* _DATETIME_HEAD_H */

(2)datetime.c

#include "datetime.h"uint32_t convert_datetime_to_seconds(const rtc_datetime_t *datetime)
{/* Number of days from begin of the non Leap-year*/uint16_t monthDays[] = {0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};uint32_t seconds = 0;/* Compute number of days from 1970 till given year*/seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;/* Add leap year number of days */seconds += ((datetime->year / 4) - (1970U / 4));/* Add number of days till given month*/seconds += monthDays[datetime->month];/* Add days in given month. We subtract the current day as it is * represented in the hours, minutes and seconds field*/seconds += (datetime->day - 1);/* For leap year if month less than or equal to February, decrement day counter*/if ((!(datetime->year & 3U)) && (datetime->month <= 2U)){seconds--;}seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) + (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;return seconds;
}void convert_seconds_to_datetime(uint32_t seconds, rtc_datetime_t *datetime)
{uint32_t x;uint32_t secondsRemaining, days;uint16_t daysInYear;/* Table of days in a month for a non leap year. First entry in the table is not used,* valid months start from 1*/uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};/* Start with the seconds value that is passed in to be converted to * date time format*/secondsRemaining = seconds;/* Calculate the number of days, we add 1 for the current day which is represented in * the hours and seconds field*/days = secondsRemaining / SECONDS_IN_A_DAY + 1;/* Update seconds left*/secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;/* Calculate the datetime hour, minute and second fields */datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;datetime->minute = secondsRemaining / 60U;datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;/* Calculate year */daysInYear = DAYS_IN_A_YEAR;datetime->year = YEAR_RANGE_START;while (days > daysInYear){/* Decrease day count by a year and increment year by 1 */days -= daysInYear;datetime->year++;/* Adjust the number of days for a leap year */if (datetime->year & 3U){daysInYear = DAYS_IN_A_YEAR;}else{daysInYear = DAYS_IN_A_YEAR + 1;}}/* Adjust the days in February for a leap year */if (!(datetime->year & 3U)){daysPerMonth[2] = 29U;}for (x = 1U; x <= 12U; x++){if (days <= daysPerMonth[x]){datetime->month = x;break;}else{days -= daysPerMonth[x];}}datetime->day = days;return;
}

3.代碼

#include "imx6ull.h"
#include "datetime.h"
void rtc_init(void)
{/*Enable Clock*/CCM_CCGR5 |= (0x3 << 18);/*NPSWA_EN [31] 1 Any software can accsee*/SNVS->HPCOMR |= (1 << 31);
}void rtc_stop(void)
{/*RTC_EN [0] 0b clear Enable*/SNVS->HPCR &= ~(1 << 0);while(SNVS->HPCR & (1 << 0)){}
}void rtc_start(void)
{/*RTC_EN [0] 1b Enable*/SNVS->HPCR |= (1 << 0);while((SNVS->HPCR & (1 << 0)) == 0){}
}void rtc_set_datetime(rtc_datetime_t *datetime)
{uint32_t seconds;rtc_stop();seconds = convert_datetime_to_seconds(datetime);SNVS->HPRTCMR = seconds >> 17;//[31:18][17:0]SNVS->HPRTCLR = seconds << 15;rtc_start();return;}void rtc_get_datetime(rtc_datetime_t *datetime)
{uint32_t tmp = 0;
uint32_t seconds = 0;do {tmp = seconds;seconds = (SNVS->HPRTCMR << 17) | (SNVS->HPRTCLR >> 15);
} while (seconds != tmp);convert_seconds_to_datetime(seconds, datetime);return;
}void rtc_test(void)
{rtc_datetime_t datetime;rtc_init();datetime.year = 2025;
datetime.month = 1;
datetime.day = 1;
datetime.hour = 21;
datetime.minute = 40;
datetime.second = 30;rtc_set_datetime(&datetime);while(1) {rtc_get_datetime(&datetime);uart_printf("%d-%d-%d  %d:%d:%d\r\n", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second);gpt_delay_sec(1);
}return;
}

五.Alarm 中斷

1. 編程思路

RTC 鬧鐘功能操作步驟

  1. 注冊 RTC 中斷
    需編寫代碼完成 RTC 中斷的注冊,使系統能響應 RTC 相關中斷事件(如鬧鐘觸發 )。

  2. 設置 RTC alarm 日期

    • Disable RTC alarm:先禁用 RTC 鬧鐘,避免設置過程中誤觸發。
    • 設置日期:配置鬧鐘觸發的具體日期、時間等參數(如年、月、日、時、分、秒 )。
    • Enable RTC alarm:啟用 RTC 鬧鐘,使配置的鬧鐘參數生效,到指定時間觸發中斷。
  3. 中斷處理函數邏輯

    • 判斷是否是 RTC alarm 中斷:在中斷處理函數中,通過檢測中斷標志等方式,識別是否由 RTC 鬧鐘觸發中斷。
    • 輸出提醒信息:若確認是 RTC alarm 中斷,輸出“鬧鐘時間到達”等提示信息(可通過串口、顯示屏等方式輸出 )。
    • 清除中斷標志:執行寫 1 清 0 操作,清除 RTC alarm 中斷標志,確保后續中斷能正常觸發。

2.代碼

int rtc_interrupt_handler(int id)
{if(SNVS->HPSR & (1 << 0)){uart_printf("RTC Alarm\r\n");//clear interruptSNVS->HPSR |= (1 << 0);while(SNVS->HPSR & (1 << 0)){}}return 0;
}void rtc_set_alarm(rtc_datetime_t *datetime)
{int seconds;// 請求 RTC 中斷:注冊中斷請求,綁定中斷處理函數
request_irq(SNVS_Consolidated_IRQn, rtc_interrupt_handler);// 禁用鬧鐘:通過操作 HPCR 寄存器,等待禁用完成
SNVS->HPCR &= ~(1 << 1);
while (SNVS->HPCR & (1 << 1)) {// 等待寄存器位清除,確保鬧鐘已禁用
}// 設置鬧鐘時間:將 datetime 轉換為秒數,拆分后寫入寄存器
seconds = convert_datetime_to_seconds(datetime);
// 高 15 位寫入 HPRTCMR([31:17] 存儲秒數高段)
SNVS->HPRTCMR = seconds >> 17;
// 低 17 位寫入 HPRTCLR([16:0] 存儲秒數低段,通過左移 15 位對齊)
SNVS->HPRTCLR = seconds << 15;//Enable alarmSNVS->HPCR |= (1 << 1);while((SNVS->HPCR & (1 << 1)) == 0){}
}

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

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

相關文章

第1篇:走進日志框架的世界 - 從HelloWorld到企業級應用

前言 在現代企業級應用開發中&#xff0c;日志系統扮演著至關重要的角色。無論是問題排查、性能監控&#xff0c;還是業務分析&#xff0c;都離不開完善的日志記錄。今天&#xff0c;我們將從零開始&#xff0c;手把手教你構建一個現代化的注解驅動日志框架。 為什么需要自定義…

173-基于Flask的微博輿情數據分析系統

基于Flask的微博輿情數據分析系統 - 技術實現與架構設計 本文詳細介紹了一個基于Flask框架開發的微博輿情數據分析系統&#xff0c;包含數據爬取、情感分析、可視化展示等完整功能模塊。 &#x1f4cb; 目錄 項目概述技術棧系統架構目錄結構核心功能模塊代碼實現數據可視化部署…

美股期權歷史市場數據波動特性分析

標題&#xff1a;基于本地CSV數據的美股期權分析與應用實踐 在金融量化研究領域&#xff0c;本地CSV數據的高效應用是開展美股期權研究的重要基礎。本文將圍繞美股期權日級別行情數據、波動率分析及策略構建的核心流程&#xff0c;詳細介紹從數據預處理到實際場景落地的關鍵方…

VUE從入門到精通二:ref、reactive、computed計算屬性、watch監聽、組件之間的通信

目錄 一、ref、reactive創建響應式對象 1、ref() 2、reactive() 3、ref和reactive的區別 二、computed計算屬性 1、什么是計算屬性computed 2、計算屬性computed和函數方法的區別 3、計算屬性computed的優勢 三、watch監聽函數 1、什么是watch&#xff1f; 2、基本語…

構建AI智能體:十二、給詞語繪制地圖:Embedding如何構建機器的認知空間

我們理解“蘋果”這個詞&#xff0c;能聯想到一種水果、一個公司、或者牛頓的故事。但對計算機而言&#xff0c;“蘋果”最初只是一個冰冷的符號或一串二進制代碼。傳統的“One-Hot”編碼方式&#xff08;如“蘋果”是[1,0,0,...]&#xff0c;“香蕉”是是[0,1,0,...]&#xff…

突擊復習清單(高頻核心考點)

&#x1f512; 鎖的作用與使用&#xff08;synchronized vs ReentrantLock&#xff09; 面試官為什么問&#xff1a;考察你對并發編程基礎的掌握程度。 速記答案&#xff1a; 作用&#xff1a;保證線程安全&#xff0c;解決多線程環境下對共享資源訪問的數據不一致問題。 synch…

2025年視頻大模型匯總、各自優勢及視頻大模型競爭焦點

文章目錄一、國際主流視頻大模型1. OpenAI Sora Turbo2. Google Veo 33. Runway Gen-3 Alpha二、國內主流視頻大模型1. 快手可靈AI2. 愛詩科技PixVerse V33. 阿里巴巴通義萬相2.14. 生數科技Vidu Q15. 字節跳動即夢AI三、核心趨勢與競爭焦點一、國際主流視頻大模型 1. OpenAI …

Android - 用Scrcpy 將手機投屏到Windows電腦上

工作生活當中&#xff0c;常常需要操作手機&#xff0c;但是用手操作顯然不如用鍵盤快。 再一個&#xff0c;你看視頻的時候&#xff0c;想做一些筆記&#xff0c;那你也得截個圖啦之類的&#xff0c; 那如果直接在電腦上能看也是非常方便的&#xff0c;這都需要投屏手機到電…

AlmaLinux 上 Python 3.6 切換到 Python 3.11

在 AlmaLinux 上將默認的 Python 3.6 升級或切換到 Python 3.11 是一個常見的需求。請注意&#xff0c;直接替換系統自帶的 Python 3.6 是非常危險的&#xff0c;因為許多系統工具&#xff08;如 yum/dnf 包管理器&#xff09;都依賴于它&#xff0c;盲目刪除或修改可能會導致系…

基于RBF-GA的鋁/鎂異材FSLW工藝參數優化研究

課題&#xff1a;基于RBF-GA的鋁/鎂異材FSLW工藝參數優化研究 1. 引言 (Introduction) 研究背景與意義&#xff1a; 輕量化需求&#xff1a;鋁&#xff08;Al&#xff09;和鎂&#xff08;Mg&#xff09;合金是航空航天、新能源汽車等領域實現輕量化的關鍵材料。實現二者的可靠…

【Prometheus】Prometheus監控Docker實戰

&#x1f47b;創作者&#xff1a;丶重明 &#x1f47b;創作時間&#xff1a;2025年8月23日 &#x1f47b;擅長領域&#xff1a;運維 目錄前言什么是Prometheus和cAdvisorPrometheuscAdvisor部署操作部署cAdvisor部署Prometheus指標說明cpu相關指標內存相關指標磁盤相關指標網絡…

2.7 提示詞調優編碼實戰(二)

目錄 四,提示詞模版優化 - 格式化 4.1 代碼示例 4.2 任務描述 4.3 模型輸出格式化 4.4 用戶輸入 4.5 輸出結果 四,提示詞模版優化 - 格式化 在簡單提示詞的基礎上,我們對提示詞模版中各部分進行格式化。包括任務描述增加了相應的字段。 同時對輸出增加了更多的定義和…

Kafka如何保證「消息不丟失」,「順序傳輸」,「不重復消費」,以及為什么會發生重平衡(reblanace)

前言 上一篇文章總結了kafka為什么快&#xff0c;下面來總結一下&#xff0c;kafka高頻的常見的問題。內容有點多&#xff0c;全部看完需要有一定的耐心。 kafka如何保證消息不丟失 Producer端 要保證消息不丟失&#xff0c;第一點要做的就是要保證消息從producer端發送到了…

原子操作匯編實現:原理、流程與代碼解析

&#x1f52c; 原子操作匯編實現&#xff1a;原理、流程與代碼解析 引用&#xff1a;VC/C Intel x86 內聯匯編實現 “Interlocked” 原子變量各種操作 &#x1f31f; 引言&#xff1a;原子操作的重要性 在多線程編程中&#xff0c;原子操作是確保數據一致性的關鍵機制。本文…

【WRF理論第十九期】內陸湖泊、水體的處理方式

目錄 WRF 模型中湖泊模擬概述 湖泊模型(Lake Model)集成 新增湖泊數據支持(如 WUDAPT + MODIS) LAKE_DEPTH Noah-MP + 湖泊模型聯合使用 namelist.input 配置說明 WRF 代碼更新 參考 論壇-WRF 湖泊模型(WRF-Lake model)與 SST 更新 WRF 模型中湖泊模擬概述 湖泊模型(La…

【滲透測試】SQLmap實戰:一鍵獲取MySQL數據庫權限

注&#xff1a;所有技術僅用于合法安全測試與防御研究&#xff0c;未經授權的攻擊行為屬違法犯罪&#xff0c;將承擔法律責任。一、SQLmap常規用法注意存放路徑&#xff1a;C:\Users\neo\AppData\Local\sqlmap\output1、列出詳細過程和數據庫列表sqlmap -u http://192.168.61.2…

LeetCode 第464場周賽 第三天

1. 3658 奇數和與偶數和的最大公約數&#xff08;歐幾里得&#xff09; 鏈接&#xff1a;題目鏈接 題解&#xff1a; 題解時間復雜度O(logmin(a, b))&#xff1a; 獲得前n個奇、偶數的總和&#xff0c;由于數列為等差數列&#xff0c;等差數列和公式&#xff1a;(a1 an) * n …

IntelliJ IDEA 集成 ApiFox 操作與注解規范指南

一、IDEA裝入Apifox 1.安裝Apifox Helper 說明:在 IntelliJ IDEA 中安裝 ApiFox Helper 插件。 2.打開Apifox 說明:點擊 設置,在菜單中選擇 API訪問令牌。在彈出的窗口中輸入任意名稱,并選擇令牌的有效期(為了方便,我這里選擇了 無期限)。生成令牌后,由于 令牌只能復…

C++---雙指針

在C編程中&#xff0c;雙指針算法是一種高效的解題思路&#xff0c;其核心是通過設置兩個指針&#xff08;或索引&#xff09;遍歷數據結構&#xff08;如數組、鏈表、字符串等&#xff09;&#xff0c;利用指針的移動規則減少無效操作&#xff0c;從而將時間復雜度從暴力解法的…