DA14585墨水屏學習

一、do_min_word

void do_min_work(void)
{timer_used_min = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES, do_min_work);current_unix_time += time_offset;time_offset = 60;// if (isconnected == 1)// {//     GPIO_SetActive(GPIO_LED_PORT, GPIO_LED_PIN);//     GPIO_SetInactive(GPIO_LED_PORT, GPIO_LED_G_PIN);//     DEV_Delay_ms(5);// }arch_printf("current_unix_time:%d\n", current_unix_time);do_time_show();if (step == 0){// do_img_save();step = 1;display();}// time_refresh_count++;// if ((time_refresh_count >= Time_To_Refresh) && (g_tm.tm_min == 0 && g_tm.tm_hour == 0))// {//     if (step == 0)//     {//         // do_img_save();//         step = 1;//         display();//     }// }// GPIO_SetActive(GPIO_LED_PORT, GPIO_LED_G_PIN);// GPIO_SetInactive(GPIO_LED_PORT, GPIO_LED_PIN);
}

這段代碼是一個定時器回調函數,用于每分鐘執行一次系統時間更新和顯示刷新操作。以下是對代碼的詳細解釋:

void do_min_work(void)
{// 1. 重新設置定時器,確保每分鐘執行一次timer_used_min = app_easy_timer(APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES, do_min_work);// 2. 時間更新邏輯current_unix_time += time_offset;  // 累加當前時間(秒)time_offset = 60;                  // 重置偏移量為60秒(1分鐘)// 3. 調試輸出當前時間arch_printf("current_unix_time:%d\n", current_unix_time);// 4. 顯示時間do_time_show();// 5. 狀態機控制(僅在step=0時執行一次)if (step == 0){step = 1;         // 切換狀態display();        // 更新顯示內容}
}

其中:APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES是一個宏,其定義如下 :

#define APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES 6000,這時是否少了一個0,不得而知。

代碼關鍵點解釋

  1. 定時器機制

    • 通過app_easy_timer函數設置一個每分鐘觸發的定時器
    • 每次回調執行時會重新設置定時器,形成循環調用
    • APP_PERIPHERAL_CTRL_TIMER_DELAY_MINUTES應定義為 60000ms(1 分鐘)
  2. 時間維護

    • current_unix_time存儲當前的 Unix 時間戳(秒)
    • time_offset初始為 60,每次累加后重置,確保每分鐘遞增 60 秒
    • 這種設計允許系統在無法獲取 RTC 時通過軟件維護時間
  3. 顯示控制

    • do_time_show():更新時間顯示
    • display():刷新整個顯示內容
    • 使用step變量實現狀態機控制,確保某些操作只執行一次
  4. 注釋代碼分析

    • 被注釋的 LED 控制代碼表明系統可能通過 LED 指示連接狀態
    • do_img_save()可能用于保存屏幕截圖或圖像數據
    • 時間刷新條件檢查(午夜 0 點)被注釋,可能用于每日特定操作

二、app_easy_timer函數

timer_hnd app_easy_timer(const uint32_t delay, timer_callback fn)
{// Sanity checksASSERT_ERROR(delay > 0);                  // Delay should not be zeroASSERT_ERROR(delay <= KE_TIMER_DELAY_MAX); // Delay should not be more than maximum allowedtimer_hnd timer_id = set_callback(fn);if (timer_id == EASY_TIMER_INVALID_TIMER){return EASY_TIMER_INVALID_TIMER; //No timers available}// Create timercreate_timer(timer_id, delay);return timer_id;
}

其中timer_hnd定義如下 :typedef uint8_t timer_hnd;

app_easy_timer 函數用于創建一個定時器,在指定的延時后執行回調函數。它提供了參數檢查、資源分配和定時器初始化的功能。

timer_hnd app_easy_timer(const uint32_t delay, timer_callback fn)
{// 1. 參數有效性檢查ASSERT_ERROR(delay > 0);                  // 延時必須大于0ASSERT_ERROR(delay <= KE_TIMER_DELAY_MAX); // 延時不能超過系統最大限制// 2. 分配定時器資源并注冊回調函數timer_hnd timer_id = set_callback(fn);if (timer_id == EASY_TIMER_INVALID_TIMER){return EASY_TIMER_INVALID_TIMER; // 沒有可用的定時器資源}// 3. 創建并啟動定時器create_timer(timer_id, delay);// 4. 返回定時器句柄供后續操作使用return timer_id;
}

核心功能分析 1. ?參數檢查:

? delay > 0:確保延時時間有效

? delay <= KE_TIMER_DELAY_MAX:防止過大的延時值導致系統異常

? ASSERT_ERROR 通常是斷言宏,參數不合法時會觸發錯誤處理 ?

2. ?資源分配:

? set_callback(fn) 函數: ? 分配一個定時器 ID

? 將傳入的回調函數 fn 與該 ID 關聯

? 返回 EASY_TIMER_INVALID_TIMER 表示資源不足 ? ?

3. ?定時器初始化:

? create_timer(timer_id, delay) 函數:

? 使用分配的 ID 配置硬件 / 軟件定時器

? 設置延時值 delay(單位通常為毫秒)

? 啟動定時器開始倒計時 ? ?

4. ?錯誤處理:

? 當無可用定時器資源時,函數會立即返回錯誤碼

? 上層應用需要檢查返回值以處理錯誤情況

5.典型使用流程

1. 調用示例:

? // 設置一個1000ms后執行的定時器
timer_hnd my_timer = app_easy_timer(1000, my_callback_function);
if (my_timer == EASY_TIMER_INVALID_TIMER) {
? ? // 處理定時器創建失敗的情況
}
? ? ?2. 回調函數定義:

?void my_callback_function(void) {
? ? // 定時器到期時執行的代碼
? ? // 例如更新狀態、觸發事件等
}

6.注意事項

1). ?定時器資源限制:

? 系統通常有最大定時器數量限制

? 未釋放的定時器會持續占用資源 ?

2). ?延時精度:

? 實際延時可能受系統負載影響

? 依賴底層定時器硬件的精度 ?

3). ?回調函數約束:

? 避免在回調中執行耗時操作

? 確保回調函數可重入(如果支持多定時器并發) ?

4. ) 資源釋放:

? 通常需要配套的定時器刪除函數(如 delete_timer(timer_hnd))

? 不再使用的定時器應及時釋放 ? ?

這個函數提供了嵌入式系統中常用的定時器功能抽象,通過分離資源分配和定時器操作,使上層應用可以更方便地使用定時服務。

7.其中set_callback函數定義如下:

***************************************************************************************** @brief Place a callback in the first available position in the timer callback array.* @param[in] fn The callback to be added* @return The handler of the timer for future reference. EASY_TIMER_INVALID_TIMER if* there is no timer available*****************************************************************************************/
static timer_hnd set_callback(timer_callback fn)
{for (int i = 0; i < APP_TIMER_MAX_NUM; i++){if (timer_callbacks[i] == NULL){timer_callbacks[i] = fn;return APP_EASY_TIMER_IDX_TO_HND(i);}}return EASY_TIMER_INVALID_TIMER;
}

這段代碼實現了一個內部函數 set_callback,用于在定時器回調數組中分配一個空閑位置并注冊回調函數。以下是對代碼的詳細解釋:set_callback 是一個靜態函數,用于從回調數組中分配一個未使用的索引,并將傳入的回調函數 fn 存儲在該位置。如果找不到空閑位置(即所有定時器都已被占用),則返回錯誤碼。


static timer_hnd set_callback(timer_callback fn)
{
? ? // 遍歷定時器回調數組,查找空閑位置
? ? for (int i = 0; i < APP_TIMER_MAX_NUM; i++)
? ? {
? ? ? ? // 如果發現某個位置為空(NULL),說明該位置未被使用
? ? ? ? if (timer_callbacks[i] == NULL)
? ? ? ? {
? ? ? ? ? ? // 將回調函數存儲到該位置
? ? ? ? ? ? timer_callbacks[i] = fn;
? ? ? ? ? ??
? ? ? ? ? ? // 將數組索引轉換為定時器句柄并返回,
? ? ? ? ? ? return APP_EASY_TIMER_IDX_TO_HND(i);
? ? ? ? }
? ? }
? ??
? ? // 如果遍歷完所有位置都沒有找到空閑位置,返回錯誤碼
? ? return EASY_TIMER_INVALID_TIMER;
}

p


其中:timer_calback 定義如下 :

//?Timer callback function type definition
typedef void (* timer_callback)(void);

此代碼解析:這段代碼定義了一個函數指針類型 timer_callback,用于表示定時器回調函數的原型。

類型定義:

? timer_callback 是一個函數指針類型,指向 無參數、無返回值 的函數。 ?

函數原型要求:

? 回調函數必須符合 void function_name(void) 的形式。

? 例如:

?void my_timer_handler(void) {
? ? // 定時器觸發時執行的代碼
}
? ? ?
? ??用途:

? 作為參數傳遞給定時器 API(如 app_easy_timer),用于注冊定時執行的任務。

? 系統在定時器到期時,會通過該函數指針調用對應的回調函數。 ? ?

典型應用場景

? ? ? ? // 定義回調函數
void update_led(void) {
? ? // 更新LED狀態
}

// 創建定時器,注冊回調
timer_hnd timer = app_easy_timer(1000, update_led); // 1秒后執行
? ? ?技術要點

1. ?函數指針語法:

? void (*)(void) 表示指向 “無參數、無返回值函數” 的指針。

? typedef 將該指針類型命名為 timer_callback,簡化后續使用。 ?

2. ?與定時器系統的關聯:

? 結合之前分析的 set_callback 函數,timer_callbacks 數組實際存儲的就是 timer_callback 類型的函數指針。

? 當定時器到期時,系統會直接調用 timer_callbacks[index]()。 ?

3. ?兼容性要求: ? 所有注冊的回調函數必須嚴格遵循 void(void) 原型,否則可能導致棧破壞或參數傳遞異常。 ? ?

注意事項

1. ?回調函數的執行環境:

? 回調函數可能在中斷上下文或低優先級任務中執行,應避免耗時操作(如阻塞 IO)。 ?

2. ?參數傳遞限制:

? 由于函數原型固定為無參數,若需傳遞上下文,可通過全局變量或閉包技術(如 C++ lambda 捕獲)。 ?

3. ?錯誤處理:

? 回調函數內部應包含必要的錯誤檢查,避免因異常導致系統崩潰。


其中:timer_callbacks數組定義如下 :

// Array that holds the callback function of the active timers
static timer_callback timer_callbacks[APP_TIMER_MAX_NUM] ? ? ? ? ?__SECTION_ZERO("retention_mem_area0");

這段代碼聲明了一個靜態數組 timer_callbacks,用于存儲系統中所有活躍定時器的回調函數。以下是詳細解釋:

數據結構:

? timer_callbacks 是一個靜態數組,大小為 APP_TIMER_MAX_NUM,表示系統最多支持的并發定時器數量。

? 數組元素類型為 timer_callback(即函數指針,指向 void (*)(void) 類型的函數)。 ?

存儲屬性:

? static 關鍵字確保數組的作用域僅限于當前文件,避免外部訪問。

? __SECTION_ZERO("retention_mem_area0") 是一個特殊的編譯器指令,

用于:

? 將數組放置在名為 "retention_mem_area0" 的內存區域。

? __SECTION_ZERO 通常表示該區域在系統復位時不會被清零(即 “保留內存”),適用于需要在睡眠 / 喚醒周期中保持狀態的場景。 ? ?

初始化:

? 由于位于 __SECTION_ZERO 區域,數組初始值為全零(即所有元素初始化為 NULL),表示無活躍定時器。 ? ?

關鍵技術點

1. ?回調函數管理:

? 數組索引對應定時器 ID,例如 timer_callbacks[0] 對應第一個定時器的回調函數。

? set_callback 函數通過線性搜索找到第一個 NULL 位置,將回調函數存入并返回索引。 ?

2. ?保留內存的作用:

? 在低功耗系統中,部分內存區域可配置為 “保留” 狀態,即使系統進入睡眠模式也不會斷電。

? 定時器回調數組位于保留區,可確保:

? 睡眠喚醒后定時器狀態不丟失。

? 無需重新初始化定時器配置。 ? ?

3. ?與硬件的關聯:

? 實際硬件定時器可能通過 ID 與數組索引映射,

例如:

?// 定時器觸發時,通過索引調用對應回調
void hardware_timer_isr(uint8_t timer_idx) {
? ? if (timer_callbacks[timer_idx] != NULL) {
? ? ? ? timer_callbacks[timer_idx](); // 執行回調
? ? }
}
? ? ?
? ? 應用場景

1. ?嵌入式系統中的定時任務:

? 周期性數據采集(如傳感器讀數)。

? 狀態機超時處理。

? 通信協議中的定時響應(如心跳包)。 ?

2. ?低功耗設計:

? 配合 RTC(實時時鐘)實現長時間定時喚醒。

? 在休眠模式下保持關鍵定時器狀態。 ?

?注意事項

1. ?內存限制:

? APP_TIMER_MAX_NUM 受保留內存區域大小限制,需根據實際需求調整。 ?

2. ?線程安全:

? 多任務環境中修改數組需加鎖保護,避免競態條件。 ?

3. ?兼容性:

? __SECTION_ZERO 是特定編譯器的擴展(如 GCC、ARMCC),不同平臺語法可能不同。 ?

?總結 該數組是定時器系統的核心數據結構,通過將回調函數存儲在保留內存區域,確保系統在休眠 / 喚醒周期中能持續管理定時任務。這種設計在資源受限的嵌入式系統中尤為重要,既能高效利用內存,又能保證關鍵狀態不丟失。


其中宏定義如下 :

#define APP_EASY_TIMER_HND_TO_MSG_ID(timer_id)    (timer_id - 1 + APP_TIMER_API_MES0)
#define APP_EASY_TIMER_MSG_ID_TO_HND(timer_msg)   (timer_msg - APP_TIMER_API_MES0 + 1)
#define APP_EASY_TIMER_HND_TO_IDX(timer_id)       (timer_id - 1)
#define APP_EASY_TIMER_IDX_TO_HND(timer_id)       (timer_id + 1)
#define APP_EASY_TIMER_HND_IS_VALID(timer_id)     ((timer_id > 0) && (timer_id <= APP_TIMER_MAX_NUM))

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

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

相關文章

微服務調試問題總結

本地環境調試。 啟動本地微服務&#xff0c;使用公共nacos配置。利用如apifox進行本地代碼調試解決調試問題。除必要的業務微服務依賴包需要下載到本地。使用mvn clean install -DskipTests進行安裝啟動前選擇好profile環境進行啟動&#xff0c;啟動前記得mvn clean清理項目。…

C#學習第22天:網絡編程

網絡編程的核心概念 1. 套接字&#xff08;Sockets&#xff09; 定義&#xff1a;套接字是網絡通信的基本單元&#xff0c;提供了在網絡中進行數據交換的端點。用途&#xff1a;用于TCP/UDP網絡通信&#xff0c;支持低級別的網絡數據傳輸。 2.協議 TCP&#xff08;Transmiss…

TWASandGWAS中GBS filtering and GWAS(1)

F:\文章代碼\TWASandGWAS\GBS filtering and GWAS README.TXT 請檢查幻燈片“Vitamaize_update_Gorelab_Ames_GBS_filtering_20191122.pptx”中關于阿姆斯&#xff08;Ames&#xff09;ID處理流程的詳細信息。 文件夾“Ames_ID_processing”包含了用于處理阿姆斯ID的文件和R…

圖像處理篇---opencv實現坐姿檢測

文章目錄 前言一、方法概述使用OpenCV和MediaPipe關鍵點檢測角度計算姿態評估 二、完整代碼實現三、代碼說明PostureDetector類find_pose()get_landmarks()cakculate_angle()evaluate_posture() 坐姿評估標準&#xff08;可進行參數調整&#xff09;&#xff1a;可視化功能&…

.Net HttpClient 使用代理功能

HttpClient 使用代理功能 實際開發中&#xff0c;HttpClient 通過代理訪問目標服務器是常見的需求。 本文將全面介紹如何在 .NET 中配置 HttpClient 使用代理&#xff08;Proxy&#xff09;功能&#xff0c;包括基礎使用方式、代碼示例、以及與依賴注入結合的最佳實踐。 注意…

【學習路線】 游戲客戶端開發入門到進階

目錄 游戲客戶端開發入門到進階&#xff1a;系統學習路線與推薦書單一、學習總原則&#xff1a;從底層出發&#xff0c;項目驅動&#xff0c;持續迭代二、推薦學習路線圖&#xff08;初學者→進階&#xff09;第一階段&#xff1a;語言基礎與編程思維第二階段&#xff1a;游戲開…

精益數據分析(57/126):創業移情階段的核心要點與實踐方法

精益數據分析&#xff08;57/126&#xff09;&#xff1a;創業移情階段的核心要點與實踐方法 在創業的浩瀚征程中&#xff0c;每一個階段都承載著獨特的使命與挑戰。今天&#xff0c;我們繼續秉持共同進步的理念&#xff0c;深入研讀《精益數據分析》&#xff0c;聚焦創業的首…

015枚舉之滑動窗口——算法備賽

滑動窗口 最大子數組和 題目描述 給你一個整數數組 nums &#xff0c;請你找出一個具有最大和的連續子數組&#xff08;子數組最少包含一個元素&#xff09;&#xff0c;返回其最大和。 原題鏈接 思路分析 見代碼注解 代碼 int maxSubArray(vector<int>& num…

微軟系統 紅帽系統 網絡故障排查:ping、traceroute、netstat

在微軟&#xff08;Windows&#xff09;和紅帽&#xff08;Red Hat Enterprise Linux&#xff0c;RHEL&#xff09;等系統中&#xff0c;網絡故障排查是確保系統正常運行的重要環節。 ping、traceroute&#xff08;在Windows中為tracert&#xff09;和netstat是三個常用的網絡…

解構認知邊界:論萬能方法的本體論批判與方法論重構——基于跨學科視閾的哲學-科學辯證

一、哲學維度的本體論批判 &#xff08;1&#xff09;理性主義的坍縮&#xff1a;從笛卡爾幻想到哥德爾陷阱 笛卡爾在《方法論》中構建的理性主義范式&#xff0c;企圖通過"普遍懷疑-數學演繹"雙重機制確立絕對方法體系。然而哥德爾不完備定理&#xff08;Gdel, 19…

【網絡入侵檢測】基于源碼分析Suricata的IP分片重組

【作者主頁】只道當時是尋常 【專欄介紹】Suricata入侵檢測。專注網絡、主機安全&#xff0c;歡迎關注與評論。 目錄 目錄 1.概要 2. 配置信息 2.1 名詞介紹 2.2 defrag 配置 3. 代碼實現 3.1 配置解析 3.1.1 defrag配置 3.1.2 主機系統策略 3.2 分片重組模塊 3.2.1…

二分查找的邊界問題

前言 二分查找(Binary Search)是一種高效的查找算法&#xff0c;時間復雜度為O(log n)。它適用于已排序的數組或列表。本文將詳細介紹二分查找的兩種常見寫法&#xff1a;閉區間寫法和左閉右開區間寫法。 一、二分查找基本思想 二分查找的核心思想是"分而治之"&am…

重慶醫科大學附屬第二醫院外科樓外擋墻自動化監測

1.項目概述 重慶醫科大學附屬第二醫院&#xff0c;重醫附二院&#xff0c;是集醫療、教學、科研、預防保健為一體的國家三級甲等綜合醫院。前身為始建于1892年的“重慶寬仁醫院”。醫院現有開放床位 1380張&#xff0c;年門診量超過百萬人次&#xff0c;年收治住院病人4.5萬人…

【Redis實戰篇】秒殺優化

1. 秒殺優化-異步秒殺思路 我們來回顧一下下單流程 當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟 1、查詢優惠卷 2、判斷秒殺庫存是否足夠 3、查詢訂單…

【idea】調試篇 idea調試技巧合集

前言&#xff1a;之前博主寫過一篇idea技巧合集的文章&#xff0c;由于技巧過于多了&#xff0c;文章很龐大&#xff0c;所以特地將調試相關的技巧單獨成章, 調試和我們日常開發是息息相關的&#xff0c;用好調試可以事半功倍 文章目錄 1. idea調試異步線程2. idea調試stream流…

postman 用法 LTS

postman 用法 LTS File ---- View ---- Show Postman Console

MySQL 數據庫故障排查指南

MySQL 數據庫故障排查指南 本指南旨在幫助您識別和解決常見的 MySQL 數據庫故障。我們將從問題識別開始&#xff0c;逐步深入到具體的故障類型和排查步驟。 1. 問題識別與信息收集 在開始排查之前&#xff0c;首先需要清晰地了解問題的現象和范圍。 故障現象&#xff1a; 數…

用AI寫簡歷是否可行?

讓AI批量寫簡歷然后投簡歷是絕對不行的&#xff01;&#xff01;&#xff01; 為什么不行&#xff0c;按照 "招聘經理" 工作經歷舉例&#xff1a; ai提示詞&#xff1a;請幫我寫一份招聘經理的工作經歷內容&#xff1a; 招聘經理 | XXX科技有限公司 | 2020年…

【從零實現JsonRpc框架#1】Json庫介紹

1.JsonCpp第三方庫 JSONCPP 是一個開源的 C 庫&#xff0c;用于解析和生成 JSON&#xff08;JavaScript Object Notation&#xff09;數據。它提供了簡單易用的接口&#xff0c;支持 JSON 的序列化和反序列化操作&#xff0c;適用于處理配置文件、網絡通信數據等場景。 2.Jso…

Ubuntu——執行echo $USE什么都不顯示

問題&#xff1a;“執行 echo $USER 什么都不顯示”&#xff1f; 一、原因分析 環境變量 $USER 未正確設置 $USER 是系統自動定義的環境變量&#xff0c;通常用于表示當前登錄的用戶名。若該變量未設置或為空&#xff0c;執行 echo $USER 會無輸出。可能場景&#xff1a; 用戶通…