一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

單片機軟件定時器的實現(xiàn)方法

CHANBAEK ? 來源:固件工人 ? 作者:固件工人 ? 2023-01-17 15:14 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1.1 背景

目前市面上的單片機基本都帶有硬件定時器功能,單片機應(yīng)用程序開發(fā)中也經(jīng)常會用到定時器進行一些和時間相關(guān)的開發(fā),比如延時或者周期性地執(zhí)行一些操作。單片機的硬件定時器個數(shù)一般都是固定的,而且一些低端單片機的定時器個數(shù)一般都比較少,在一些有多個周期性操作的應(yīng)用場合就無法滿足要求。這時,就可以基于硬件定時器派生出軟件定時器,來滿足這種多種周期性或多個單次延時操作的需求。軟件定時器的優(yōu)點就是個數(shù)可以根據(jù)實際需求進行靈活配置,而且可以實現(xiàn)多種不同的定時周期。

1.2 測試平臺

這里使用的開發(fā)環(huán)境和相關(guān)硬件如下。

  • 操作系統(tǒng):Ubuntu 20.04.2 LTS x86_64(使用uname -a命令查看)
  • 集成開發(fā)環(huán)境(IDE):Eclipse IDE for Embedded C/C++ Developers,Version: 2021-06 (4.20.0)
  • 硬件開發(fā)板:STM32F429I-DISCO
  • 本文對應(yīng)的例程代碼鏈接如下。

https://download.csdn.net/download/goodrenze/85106391

1.3 軟件定時器實現(xiàn)方法

這里就結(jié)合開發(fā)板STM32F429I-DISCO上的STM32F429ZI的單片機來演示軟件定時器的實現(xiàn)方法。

一般定時器的計數(shù)方式有2種:一種是單次定時,即定時時間到了之后,自動停止定時;另一種是周期定時,定時時間到了之后,自動按照之前的定時周期重新定時。對于周期定時,可以手動進行定時器的啟動、關(guān)閉和刪除。

下面講解軟件定時器的實現(xiàn)步驟。

1)由于軟件定時器是基于硬件定時器的,所以需要先初始化一個硬件定時器,并啟動硬件定時器。這里使用STM32F429ZI的硬件定時器7,定時器的定時周期為10ms,即每10ms產(chǎn)生一次定時器中斷。初始化代碼如下。

TIM_HandleTypeDef    Tim7Handle;
uint8_t InitTim7(uint32_t period_ms)
{
  uint16_t uwPrescalerValue;


  if(0 == period_ms)
  {
    return 1;
  }


  __HAL_RCC_TIM7_CLK_ENABLE();


  HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0);


  HAL_NVIC_EnableIRQ(TIM7_IRQn);


  /* Compute the prescaler value to have TIM7 counter clock equal to 10 KHz */
  uwPrescalerValue = (uint32_t) ((SystemCoreClock /2) / 10000) - 1;


  /* Set TIM7 instance */
  Tim7Handle.Instance = TIM7;
  Tim7Handle.Init.Period = period_ms * 10 - 1;
  Tim7Handle.Init.Prescaler = uwPrescalerValue;
  Tim7Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  Tim7Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
  if(HAL_TIM_Base_Init(&Tim7Handle) != HAL_OK)
  {
    return 1;
  }


  /* Start the TIM Base generation in interrupt mode */
  if(HAL_TIM_Base_Start_IT(&Tim7Handle) != HAL_OK)
  {
    return 1;
  }


  return 0;
}

2)硬件定時器定時時間到了之后,會產(chǎn)生中斷,所以需要實現(xiàn)定時器中斷處理函數(shù)。這里基于STM32的HAL進行開發(fā),所以在定時器的中斷入口函數(shù)中直接調(diào)用HAL_TIM_IRQHandler()函數(shù),然后實現(xiàn)實際的中斷處理回調(diào)函數(shù)HAL_TIM_PeriodElapsedCallback()。對應(yīng)的代碼如下。其中調(diào)用的軟件定時器更新函數(shù)會在后面介紹。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim == &Tim7Handle)
  {
    SwTimerUpdateCount();
  }
}

3)設(shè)計軟件定時器對應(yīng)的結(jié)構(gòu)體。按照軟件定時器的實際使用特點,必須要包含定時器計數(shù)值和周期定時器的重裝載值,另外還要有定時器時間到之后需要執(zhí)行的回調(diào)函數(shù)。對應(yīng)的軟件定時器結(jié)構(gòu)體如下所示。當(dāng)結(jié)構(gòu)體中的TimerCount和TimerReload都為0時,說明軟件定時器處于空閑狀態(tài),可以分配使用;如果TimerCount非0,而TimerReload為0,說明軟件定時器是單次定時器;如果TimerCount和TimerReload都非0,說明軟件定時器是周期定時器。

typedef void (*TimerCallbackFunc)(void);


typedef struct _SwTimer_t
{
  uint32_t TimerCount;
  uint32_t TimerReload;
  TimerCallbackFunc TimerCallback;
}SwTimer_t;

4)這里將軟件定時器設(shè)置成10個,可以通過宏定義來設(shè)置軟件定時器個數(shù)。使用軟件定時器結(jié)構(gòu)體定義一個具有10個定時器的數(shù)組。如下代碼所示。

#define SW_TIMER_NUM    10
SwTimer_t SwTimer[SW_TIMER_NUM];

5)軟件定時器復(fù)位函數(shù),用于實現(xiàn)所有軟件定時器的重置操作,重置后,所有軟件定時器都處于空閑狀態(tài),可供分配使用。函數(shù)代碼如下。

void SwTimerReset(void)
{
  uint8_t i;


  for(i = 0; i < SW_TIMER_NUM; i++)
  {
    SwTimer[i].TimerCount = 0;
    SwTimer[i].TimerReload = 0;
    SwTimer[i].TimerCallback = 0;
  }
}

6)啟動單次定時器函數(shù),用于實現(xiàn)單次定時,定時時間到了之后,執(zhí)行對應(yīng)回調(diào)函數(shù),并停止定時和釋放定時器資源。函數(shù)代碼如下。如果啟動成功,函數(shù)返回定時器的索引號(該值小于定時器個數(shù)值);啟動失敗,返回的定時器索引號等于定時器的個數(shù)。

uint8_t SwTimerStartSingleTimer(uint32_t single_ms, TimerCallbackFunc TimerCallback)
{
  uint8_t i;


  single_ms /= MINI_PERIOD_MS;
  if(0 == single_ms)
  {
    single_ms = 1;
  }
  for(i = 0; i < SW_TIMER_NUM; i++)
  {
    if((SwTimer[i].TimerCount == 0) && (SwTimer[i].TimerReload == 0))
    {
      SwTimer[i].TimerCount = single_ms;
      SwTimer[i].TimerCallback = TimerCallback;
      break;
    }
  }


  return i;
}

7)添加周期定時器函數(shù),用于添加一個新的周期定時器但不啟動定時,需要手動啟動定時器。函數(shù)代碼如下。如果添加成功,函數(shù)返回定時器的索引號(該值小于定時器個數(shù)值);添加失敗,返回的定時器索引號等于定時器的個數(shù)。

uint8_t SwTimerAddPeriodTimer(uint32_t period_ms, TimerCallbackFunc TimerCallback)
{
  uint8_t i;


  period_ms /= MINI_PERIOD_MS;
  if(0 == period_ms)
  {
    period_ms = 1;
  }
  for(i = 0; i < SW_TIMER_NUM; i++)
  {
    if((SwTimer[i].TimerCount == 0) && (SwTimer[i].TimerReload == 0))
    {
      SwTimer[i].TimerReload = period_ms;
      SwTimer[i].TimerCallback = TimerCallback;
      break;
    }
  }


  return i;
}

8)啟動周期定時器函數(shù),用于啟動指定定時器索引號的周期定時器開始定時。函數(shù)代碼如下。如果啟動成功,函數(shù)返回定時器的索引號(該值小于定時器個數(shù)值);啟動失敗,返回的定時器索引號等于定時器的個數(shù)。

uint8_t SwTimerStartPeroidTimer(uint8_t timer_no)
{
  if(SW_TIMER_NUM <= timer_no)
  {
    return SW_TIMER_NUM;
  }
  else if((SwTimer[timer_no].TimerCount == 0) && (SwTimer[timer_no].TimerReload == 0))
  {
    return SW_TIMER_NUM;
  }
  else
  {
    SwTimer[timer_no].TimerCount = SwTimer[timer_no].TimerReload;
    return timer_no;
  }
}

9)停止定時器函數(shù),用于結(jié)束指定定時器索引號的定時器的定時,可用于停止單次或周期定時器。函數(shù)代碼如下。如果停止成功,函數(shù)返回定時器的索引號(該值小于定時器個數(shù)值);停止失敗,返回的定時器索引號等于定時器的個數(shù)。

uint8_t SwTimerStopTimer(uint8_t timer_no)
{
  if(SW_TIMER_NUM <= timer_no)
  {
    return SW_TIMER_NUM;
  }
  else
  {
    SwTimer[timer_no].TimerCount = 0;
    return timer_no;
  }
}

10)刪除周期定時器函數(shù),用于結(jié)束指定定時器索引號的周期定時器的定時,并釋放定時器資源。函數(shù)代碼如下。如果刪除成功,函數(shù)返回定時器的索引號(該值小于定時器個數(shù)值);刪除失敗,返回的定時器索引號等于定時器的個數(shù)。

uint8_t SwTimerDeletePeroidTimer(uint8_t timer_no)
{
  if(SW_TIMER_NUM <= timer_no)
  {
    return SW_TIMER_NUM;
  }
  else
  {
    SwTimer[timer_no].TimerCount = 0;
    SwTimer[timer_no].TimerReload = 0;
    return timer_no;
  }
}

11)軟件定時器計數(shù)值更新函數(shù),用于更新每個已經(jīng)啟動定時的軟件定時器的計數(shù)值,該函數(shù)必須在硬件定時器的中斷處理函數(shù)中調(diào)用。函數(shù)的實現(xiàn)思路是:遍歷所有的軟件定時器,如果遍歷到的定時器的計數(shù)值非0,則進行減1操作。如果減1后計數(shù)值為0,如果定時器的重裝載值非0,說明是周期定時器,需要將計數(shù)值更新成對應(yīng)的重裝載值以便重新定時,同時執(zhí)行對應(yīng)的回調(diào)函數(shù);如果定時器的重裝載值是0,說明是單次定時器,執(zhí)行完回調(diào)函數(shù)后自動停止定時并釋放定時器資源。如果減1后計數(shù)值不為0,繼續(xù)遍歷更新后續(xù)的定時器,直到所有定時器都遍歷完畢。函數(shù)流程圖和對應(yīng)代碼如下。

圖1 軟件定時器計數(shù)值更新函數(shù)

void SwTimerUpdateCount(void)
{
  uint8_t i;


  for(i = 0; i < SW_TIMER_NUM; i++)
  {
    if(SwTimer[i].TimerCount != 0)
    {
      SwTimer[i].TimerCount -= 1;
      if(SwTimer[i].TimerCount == 0)
      {
        if(SwTimer[i].TimerReload != 0)
        {
          SwTimer[i].TimerCount = SwTimer[i].TimerReload;
        }
        if(SwTimer[i].TimerCallback != 0)
        {
          SwTimer[i].TimerCallback();
        }
      }
    }
  }
}

12)軟件定時器的實際使用示例。代碼如下。

int main(void)
{
  uint8_t no;


  HAL_Init();


  /* Configure the system clock to 168 MHz */
  SystemClock_Config();


  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);
  InitTim7(MINI_PERIOD_MS);
  SwTimerReset();
  no = SwTimerAddPeriodTimer(500, ToggleLed3);
  if(no < SW_TIMER_NUM)
  {
    SwTimerStartPeroidTimer(no);
  }
#if 1
  no = SwTimerAddPeriodTimer(1000, ToggleLed4);
  if(no < SW_TIMER_NUM)
  {
    SwTimerStartPeroidTimer(no);
  }
#else
  no = SwTimerStartSingleTimer(5000, ToggleLed4);
#endif


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

    關(guān)注

    6067

    文章

    44990

    瀏覽量

    650372
  • STM32
    +關(guān)注

    關(guān)注

    2293

    文章

    11032

    瀏覽量

    364819
  • 軟件定時器
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    6941
  • 定時器
    +關(guān)注

    關(guān)注

    23

    文章

    3298

    瀏覽量

    118896
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4380

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    單片機定時器的用法

    本章以CW32通用定時器為例介紹單片機定時器的用法。
    的頭像 發(fā)表于 01-04 10:37 ?2035次閱讀
    <b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>的用法

    Winbond 51單片機定時器初值計算(工具軟件)

    Winbond 51單片機定時器初值計算(工具軟件)
    發(fā)表于 06-14 07:53 ?237次下載

    單片機視頻教程06:使用定時器方法

    《手把手教你學(xué)單片機單片機視頻教程06:使用定時器方法 單片機視頻教程06:使用定時器
    發(fā)表于 08-21 09:33 ?1.7w次閱讀
    <b class='flag-5'>單片機</b>視頻教程06:使用<b class='flag-5'>定時器</b>的<b class='flag-5'>方法</b>

    51單片機定時器計算軟件

    電子發(fā)燒友網(wǎng)站提供《51單片機定時器計算軟件.zip》資料免費下載
    發(fā)表于 08-10 12:48 ?1次下載

    基于51單片機定時器2的操作與實現(xiàn)

    基于51單片機定時器2的操作與實現(xiàn),51單片機定時器2的使用!
    發(fā)表于 02-22 17:53 ?14次下載

    52單片機有幾個定時器?52單片機定時器1和52單片機定時器2程序?qū)Ρ?/a>

    52單片機有幾個定時器?STC89C52RC其實是有三個定時器單片機,STC89C52RC共有3個定時器,分別是T0、T1、T2。而51
    發(fā)表于 11-10 14:30 ?3.6w次閱讀

    如何基于51單片機利用定時器實現(xiàn)PWM的方法詳細概述

    51單片機是可以輸出PWM的,比較的麻煩。此時需要用到內(nèi)部定時器實現(xiàn),可用兩個定時器實現(xiàn),也可以用一個
    的頭像 發(fā)表于 06-12 20:01 ?3.4w次閱讀

    ESP8266的管腳的控制和軟件定時器的使用

    先說定時器,ESP8266內(nèi)部的定時器分為軟件定時器和硬件定時器。手冊中指出硬件定時器其實就跟
    的頭像 發(fā)表于 07-29 14:57 ?9910次閱讀
    ESP8266的管腳的控制和<b class='flag-5'>軟件</b><b class='flag-5'>定時器</b>的使用

    使用單片機實現(xiàn)定時器的程序免費下載

      本文檔的主要內(nèi)容詳細介紹的是使用單片機實現(xiàn)定時器的程序免費下載。
    發(fā)表于 06-05 17:35 ?6次下載
    使用<b class='flag-5'>單片機</b><b class='flag-5'>實現(xiàn)</b><b class='flag-5'>定時器</b>的程序免費下載

    基于單片機定時器的設(shè)計方法

    單片機實現(xiàn)一個定時器只要對單片機里的特殊寄存進行設(shè)置就可以實現(xiàn)了,下面我與朋友們說說這個0到
    的頭像 發(fā)表于 11-02 16:58 ?1.1w次閱讀
    基于<b class='flag-5'>單片機</b>的<b class='flag-5'>定時器</b>的設(shè)計<b class='flag-5'>方法</b>

    基于51單片機定時器

    設(shè)計思路。這樣自己拿到任何型號的51單片機,只要有原理圖,都可以自主設(shè)計。博主剛接觸單片機,才疏學(xué)淺,可能會出現(xiàn)設(shè)計不足和錯誤,歡迎大家評論區(qū)交流。^ _ ^/********************************************************
    發(fā)表于 11-04 21:06 ?35次下載
    基于51<b class='flag-5'>單片機</b>的<b class='flag-5'>定時器</b>

    51單片機——定時器

    51單片機——定時器為什么使用定時器?定時器原理?定時器設(shè)置中斷配置源代碼為什么使用定時器?之前
    發(fā)表于 11-11 16:36 ?40次下載
    51<b class='flag-5'>單片機</b>——<b class='flag-5'>定時器</b>

    51單片機定時器中斷

    定時器介紹:51單片機定時器屬于單片機的內(nèi)部資源,其電路連接和運轉(zhuǎn)均在單片機的內(nèi)部完成定時器
    發(fā)表于 11-11 19:36 ?7次下載
    51<b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>中斷

    51單片機定時器/計數(shù)

    CPU的參與。3、51單片機中的 定時器/計數(shù) 是根據(jù) 機器內(nèi)部的時鐘 或者是 外部的脈沖信號 對寄存中的數(shù)據(jù)加1。4、有了 定時器/計
    發(fā)表于 11-20 20:06 ?47次下載
    51<b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>/計數(shù)<b class='flag-5'>器</b>

    51單片機定時器中斷

    定時器介紹:51單片機定時器屬于單片機的內(nèi)部資源,其電路連接和運轉(zhuǎn)均在單片機的內(nèi)部完成定時器
    發(fā)表于 11-20 20:36 ?15次下載
    51<b class='flag-5'>單片機</b><b class='flag-5'>定時器</b>中斷