亚洲精品久久久久久久久久久,亚洲国产精品一区二区制服,亚洲精品午夜精品,国产成人精品综合在线观看,最近2019中文字幕一页二页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

一款可無限擴展的軟件定時器MultiTimer

strongerHuang ? 來源:Mculover666 ? 作者:Mculover666 ? 2021-11-16 09:23 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. MultiTimer

今天給大家?guī)淼拈_源項目是 MultiTimer,一款可無限擴展的軟件定時器,作者0x1abin,目前收獲 95 個 star,遵循 MIT 開源許可協(xié)議。

MultiTimer 是一個軟件定時器擴展模塊,可無限擴展你所需的定時器任務,取代傳統(tǒng)的標志位判斷方式, 更優(yōu)雅更便捷地管理程序的時間觸發(fā)時序。

項目地址:https://github.com/0x1abin/MultiTimer

2. 移植MultiTimer

2.1. 移植思路

開源項目在移植過程中主要參考項目的readme文檔,一般只需兩步:

  • ① 添加源碼到裸機工程中;
  • ② 實現(xiàn)需要的接口;

2.2. 準備裸機工程

本文中我使用的是小熊派IoT開發(fā)套件,主控芯片為STM32L431RCT6:

移植之前需要準備一份裸機工程,我使用STM32CubeMX生成,需要初始化以下配置:

  • 配置一個串口用于打印信息
  • printf重定向

2.3. 添加MultiTimer到工程中

① 復制MultiTimer源碼到工程中

② 在keil中添加 MultiTimer的源碼文件

③ 將MultiTimer頭文件路徑添加到keil中

3. 使用MultiTimer

使用時包含頭文件:

#include "multi_timer.h"

如果遇到multi_timer.c文件中NULL宏定義報錯,則在multi_timer.h中添加頭文件即可。

3.1. 創(chuàng)建Timer對象

/* USER CODE BEGIN PV */struct Timer timer1;struct Timer timer2;
/* USER CODE END PV */

3.2. Timer回調(diào)函數(shù)

/* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */void timer1_callback(){    printf("timer1 timeout!
");}
void timer2_callback(){    printf("timer2 timeout!
");}/* USER CODE END 0 */

3.3. 初始化并啟動Timer

始化定時器對象,注冊定時器回調(diào)處理函數(shù),設置定時時間(ms),循環(huán)定時觸發(fā)時間:

/* USER CODE BEGIN 2 */printf("multi timer test...
");
//重復計時,周期為1000次,即1000ms=1stimer_init(&timer1, timer1_callback, 1000, 1000);timer_start(&timer1);
//單次計時,周期為50次,即50mstimer_init(&timer2, timer2_callback, 50, 0);timer_start(&timer2);
/* USER CODE END 2 */

3.4. Timer對象處理

在循環(huán)中調(diào)用Timer對象處理函數(shù),處理函數(shù)會判斷鏈表上的每個定時器是否超時,如果超過,則拉起注冊的回調(diào)函數(shù):

/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */  timer_loop();} /* USER CODE END 3 */

3.5. 提供Timer時基信號

MultiTimer中所有的定時器都是通過一個32位的計數(shù)值_timer_ticks來判斷的,所以需要一個硬件定時器提供時基信號,遞增該值。

本文中使用的是STM32HAL庫,所以通過Systick來提供,無需設置額外的定時器。

main.c文件的最后編寫Systick回調(diào)函數(shù):

/* USER CODE BEGIN 4 */void HAL_SYSTICK_Callback(void){    //給multitimer提供時基信號    timer_ticks(); //1ms ticks}
/* USER CODE END 4 */

然后在stm32l4xx_it.c中調(diào)用該回調(diào)函數(shù):

/**  * @brief This function handles System tick timer.  */void SysTick_Handler(void){  /* USER CODE BEGIN SysTick_IRQn 0 */  HAL_SYSTICK_IRQHandler();
  /* USER CODE END SysTick_IRQn 0 */  HAL_IncTick();  /* USER CODE BEGIN SysTick_IRQn 1 */
  /* USER CODE END SysTick_IRQn 1 */}

接下來編譯下載,看在串口助手中看到打印的日志:b416dbb8-4441-11ec-b939-dac502259ad0.png

4. MultiTimer設計思想解讀

4.1. 軟件定時器設計思想

MultiTimer的設計比較簡潔。

設置一個計數(shù)值_timer_ticks不斷遞增,由定時器提供的中斷驅(qū)動,只計次數(shù),不計時間,有了很大的自由度,一般時基信號設置為1ms一次:

/**  * @brief  background ticks, timer repeat invoking interval 1ms.  * @param  None.  * @retval None.  */void timer_ticks(){  _timer_ticks++;}

在程序運行時循環(huán)比較定時器設置的超時值是否大于當前_timer_ticks的計數(shù)值,如果是則再次判斷是否重復計數(shù)值是否為0,是則停止定時器,完成單次計時效果,否則修改計數(shù)值,最后拉起注冊到該定時器的回調(diào)函數(shù)執(zhí)行:

/**  * @brief  main loop.  * @param  None.  * @retval None  */void timer_loop(){  struct Timer* target;  for(target=head_handle; target; target=target->next) {    if(_timer_ticks >= target->timeout) {      if(target->repeat == 0) {        timer_stop(target);      } else {        target->timeout = _timer_ticks + target->repeat;      }      target->timeout_cb();    }  }}

4.2. 單鏈表操作

MultiTimer的代碼少,非常適合拿來學習單鏈表的操作,學習數(shù)據(jù)結(jié)構(gòu)的過程是乏味的,不如直接來個實例看看是如何操作的。

① 鏈表的節(jié)點設計為一個軟件定時器,所以理論上支持的定時器數(shù)量只受內(nèi)存限制。

typedef struct Timer {    uint32_t timeout;    uint32_t repeat;    void (*timeout_cb)(void);    struct Timer* next;}Timer;

定時器初始化函數(shù)timer_init就是初始化一個鏈表節(jié)點:

void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat){  // memset(handle, sizeof(struct Timer), 0);  handle->timeout_cb = timeout_cb;  handle->timeout = _timer_ticks + timeout;  handle->repeat = repeat;}

② 設置鏈表頭指針,只需知道頭指針就能完成對整個單鏈表的操作:

//timer handle list head.static struct Timer* head_handle = NULL;

③ 向單鏈表增加一個節(jié)點

向單鏈表增加一個節(jié)點有三種方式:

  • 在單鏈表尾部增加一個節(jié)點
  • 在單鏈表頭部增加一個節(jié)點
  • 在單鏈表中間增加一個節(jié)點

MultiTimer中所有的結(jié)點都是定時器,每個定時器之間相互獨立,不存在先后次序關系,所以無論加到中間,還是加到尾部,還是加到頭部,最后的功能都是一樣的,但是在插入算法上有優(yōu)劣性能之分。

先來看看再單鏈表尾部增加一個節(jié)點的算法:b4a1d22c-4441-11ec-b939-dac502259ad0.gif( 我會動哦 )

int timer_start(struct Timer* handle){  /**    * 算法1 —— 向單鏈表尾部添加節(jié)點   * 時間復雜度O(n)   * Mculover666   */  struct Timer* target = head_handle;  if(head_handle == NULL)  {    /* 鏈表為空 */    head_handle = handle;    handle->next = NULL;  }  else  {    /* 鏈表中存在節(jié)點,遍歷找最后一個節(jié)點 */    while(target->next != NULL)    {      if(target == handle)        return -1;      target = target->next;    }    target->next = handle;    handle->next = NULL;  }
  return 0;}

這種算法理解簡單,實現(xiàn)簡單,但是算法時間復雜度秒變?yōu)镺(n),當n很大時,插入一個節(jié)點的時間就會非常久。

再來看看在鏈表頭部插入一個新節(jié)點的情況:

(我會動哦)

int timer_start(struct Timer* handle){  /**    * 算法2 —— 向單鏈表頭部添加節(jié)點   * 時間復雜度O(n),如果去掉判斷重復,則時間復雜度O(1)   * 0x1abin   */   struct Timer *target = head_handle;
   //判斷是否有重復的定時器   while(target)   {    if(target == handle)    {      return -1;    }    target = target->next;   }   handle->next = head_handle;   head_handle = handle;   return 0;}

這里第二種頭部插入節(jié)點的算法時間復雜度依然是O(n),emmm?

其實,這里因為單鏈表節(jié)點是定時器,在插入的時候需要對整個鏈表進行判斷,避免重復添加同樣的定時器節(jié)點,所以無論任何一種算法,都需要對單鏈表進行遍歷。

如果在不需要判斷重復的情況下,尾部插入算法仍然需要遍歷,但是頭部插入算法只需要插入就可以,時間復雜度為O(1),算法更優(yōu)。

④ 單鏈表刪除其中一個節(jié)點

刪除單鏈表的節(jié)點時,因為節(jié)點自身只保存有下一個節(jié)點的指針,并沒有指向上一個節(jié)點的指針,所以不能直接入手刪除節(jié)點,那么如何刪除單鏈表的節(jié)點呢?

方法是:設置二級指針(指向Timer類型指針的指針),通過遍歷鏈表的方式來尋找節(jié)點中next指針指向刪除節(jié)點的那個節(jié)點,代碼如下。

void timer_stop(struct Timer* handle){  struct Timer** curr;  for(curr = &head_handle; *curr; ) {    struct Timer* entry = *curr;    if (entry == handle) {      *curr = entry->next;//      free(entry);    } else      curr = &entry->next;  }}

責任編輯:haq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 軟件
    +關注

    關注

    69

    文章

    5266

    瀏覽量

    90611
  • 定時器
    +關注

    關注

    23

    文章

    3350

    瀏覽量

    121427

原文標題:MultiTimer,一款可無限擴展的軟件定時器

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    SysTick系統(tǒng)滴答定時器簡介

    SysTick—系統(tǒng)定時器是屬于CM33內(nèi)核中的個外設,內(nèi)嵌在NVIC中。系統(tǒng)定時器個24bit的向下遞減的計數(shù),計數(shù)
    的頭像 發(fā)表于 09-23 09:50 ?1154次閱讀
    SysTick系統(tǒng)滴答<b class='flag-5'>定時器</b>簡介

    TPL5100 ACTIVE 具有電源門控功能和 MOS 驅(qū)動的 Nano 供電可編程定時器

    TPL5100 是一款針對低功耗應用優(yōu)化的長期定時器 IC。該TPL5100可以替換微控制的內(nèi)部定時器,使微控制保持完全關閉而不是運行
    的頭像 發(fā)表于 09-15 09:45 ?397次閱讀
    TPL5100 ACTIVE 具有電源門控功能和 MOS 驅(qū)動<b class='flag-5'>器</b>的 Nano 供電可編程<b class='flag-5'>定時器</b>

    ?TPL5110 低功耗定時器技術文檔總結(jié)

    TPL5110 Nano 定時器一款低功耗定時器,集成了 MOSFET 驅(qū)動,設計用于占空比或電池供電應用中的功率門控。該TPL5110僅消耗 35 nA,可以使能電源線并大幅降低
    的頭像 發(fā)表于 09-14 10:50 ?849次閱讀
    ?TPL5110 低功耗<b class='flag-5'>定時器</b>技術文檔總結(jié)

    TPL5111 超低功耗系統(tǒng)定時器技術手冊

    TPL5111 Nano 定時器一款低功耗系統(tǒng)定時器,設計用于占空比或電池供電應用中的功率門控。該TPL5111僅消耗 35 nA,可用于使能和禁用微控制或其他系統(tǒng)設備的電源,從而
    的頭像 發(fā)表于 09-14 10:07 ?839次閱讀
    TPL5111 超低功耗系統(tǒng)<b class='flag-5'>定時器</b>技術手冊

    ?TPL5010-Q1 納米功耗系統(tǒng)定時器(帶看門狗功能)技術文檔摘要

    TPL5010-Q1 Nano 定時器一款低功耗、符合 AEC-Q100 標準的定時器,帶有看門狗 該功能非常適合占空比或電池供電應用中的系統(tǒng)喚醒。在這樣的系統(tǒng)中 微控制
    的頭像 發(fā)表于 09-13 10:01 ?1128次閱讀
    ?TPL5010-Q1 納米功耗系統(tǒng)<b class='flag-5'>定時器</b>(帶看門狗功能)技術文檔摘要

    大彩講堂:VisualHMI-LUA教程-定時器的使用指南

    定時器的使用
    的頭像 發(fā)表于 08-31 16:59 ?736次閱讀
    大彩講堂:VisualHMI-LUA教程-<b class='flag-5'>定時器</b>的使用指南

    TPS3435 Nano IQ精密超時看門狗定時器技術解析與應用指南

    Texas Instruments TPS3435/TPS3435-Q1 Nano I~Q~ 精確超時看門狗定時器一款250nA(典型值)超低功耗器件,具有可編程超時看門狗定時器。該看門狗
    的頭像 發(fā)表于 08-26 16:20 ?610次閱讀
    TPS3435 Nano IQ精密超時看門狗<b class='flag-5'>定時器</b>技術解析與應用指南

    德州儀器TPS3436-Q1汽車級窗口看門狗定時器技術解析

    Texas Instruments TPS3436-Q1精密窗口看門狗定時器一款超低功耗(250nA典型值)器件,提供可編程窗口看門狗定時器。TPS3436-Q1可提供具有多種功能的高精度超時
    的頭像 發(fā)表于 08-18 14:54 ?590次閱讀
    德州儀器TPS3436-Q1汽車級窗口看門狗<b class='flag-5'>定時器</b>技術解析

    Texas Instruments DS160PT801X16EVM重定時器評估模塊數(shù)據(jù)手冊

    Texas Instruments DS160PT801X16EVM重定時器評估模塊(EVM)是一款16通道PCIe轉(zhuǎn)接卡板,用于評估DS160PT801 PCIe Gen4重定時器。該評估模塊采用
    的頭像 發(fā)表于 07-29 15:25 ?417次閱讀
    Texas Instruments DS160PT801X16EVM重<b class='flag-5'>定時器</b>評估模塊數(shù)據(jù)手冊

    MCU定時器/計數(shù)

    RISC-V核低功耗MCU通過靈活的定時器架構(gòu)、低功耗模式適配及硬件級中斷優(yōu)化,在工業(yè)控制、智能家居等場景中實現(xiàn)高精度計時與能耗控制的協(xié)同設計,滿足復雜任務調(diào)度與實時響應的雙重需求?。 、?硬件
    的頭像 發(fā)表于 04-27 13:54 ?530次閱讀

    TPS3435 納米靜態(tài)電流精密超時看門狗定時器數(shù)據(jù)手冊

    TPS3435 是一款超低功耗 (典型值為 250nA) 器件,提供可編程超時看門狗定時器。 TPS3435 提供高精度超時看門狗定時器,具有適用于各種應用的系列功能。超時看門
    的頭像 發(fā)表于 04-09 15:49 ?646次閱讀
    TPS3435 納米靜態(tài)電流精密超時看門狗<b class='flag-5'>定時器</b>數(shù)據(jù)手冊

    TPS3436-Q1 汽車級納米靜態(tài)電流精密窗口看門狗定時器數(shù)據(jù)手冊

    TPS3436-Q1 是一款超低功耗(典型值為 250 nA)器件,提供可編程窗口看門狗定時器。 TPS3436-Q1 提供高精度窗口看門狗定時器,具有許多功能,適用于各種應用。關閉窗口
    的頭像 發(fā)表于 04-09 14:40 ?549次閱讀
    TPS3436-Q1 汽車級納米靜態(tài)電流精密窗口看門狗<b class='flag-5'>定時器</b>數(shù)據(jù)手冊

    TPS3435-Q1 汽車級納米靜態(tài)電流精密超時看門狗定時器數(shù)據(jù)手冊

    TPS3435-Q1 是一款超低功耗 (典型值為 250nA) 器件,提供可編程超時看門狗定時器。 TPS3435-Q1 提供高精度超時看門狗定時器,具有許多功能,適用于各種應用。超時看門狗
    的頭像 發(fā)表于 04-09 14:34 ?536次閱讀
    TPS3435-Q1 汽車級納米靜態(tài)電流精密超時看門狗<b class='flag-5'>定時器</b>數(shù)據(jù)手冊

    圣邦微電子SGM819SxQ車規(guī)級看門狗定時器電路特性與數(shù)據(jù)手冊分享

    SGM819SxQ 是一款獨立的看門狗定時器電路,它可以幫助防止因硬件故障(例如外圍設備錯誤、總線占用)或軟件故障(例如循環(huán)中無限執(zhí)行的代碼)導致的系統(tǒng)故障。 該器件配備了 WDI 輸
    的頭像 發(fā)表于 02-26 17:34 ?2041次閱讀
    圣邦微電子SGM819SxQ車規(guī)級看門狗<b class='flag-5'>定時器</b>電路特性與數(shù)據(jù)手冊分享

    圣邦微電子車規(guī)級看門狗定時器電路SGM819SxQ特性與典型應用電路

    圣邦微電子推出 SGM819SxQ,一款車規(guī)級看門狗定時器電路。 該器件適用于汽車應用、工業(yè)設備、電信、安全應用、網(wǎng)絡、醫(yī)療設備和不間斷電源系統(tǒng)。 SGM819SxQ 是一款獨立的看門狗定時器
    的頭像 發(fā)表于 02-26 09:13 ?1562次閱讀
    圣邦微電子車規(guī)級看門狗<b class='flag-5'>定時器</b>電路SGM819SxQ特性與典型應用電路