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

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

3天內不再提示

使用STM32定時器測量程序執(zhí)行時間的方法詳解

CHANBAEK ? 來源:固件工人 ? 作者:固件工人 ? 2023-01-17 15:11 ? 次閱讀

1.1 背景

單片機的固件開發(fā)過程中,有的時候需要評估固件代碼的執(zhí)行性能,會對部分關鍵程序代碼的執(zhí)行時間進行測量。通常會用到的測量程序執(zhí)行時間的方法是使用示波器進行測量。一般步驟是借助單片機的某一個GPIO口,假設默認情況下GPIO口置1;在需要測量的程序代碼開始處將GPIO口清0,然后執(zhí)行程序代碼段,在代碼段的終止處將GPIO口重新置1;示波器設置成邊沿觸發(fā)方式,抓取GPIO口從清0到重新置1的這段波形,然后用示波器卡出GPIO口下降沿到上升沿的這段時間,也就是程序代碼段的執(zhí)行時間。

以上方法的不足之處在于需要用到示波器,而且需要借用MCU的一個GPIO進行輔助測量,靈活性也欠佳,實際使用不是太方便。那有沒有更簡便的測量方法呢?答案是肯定的,那就是使用MCU的定時器進行程序執(zhí)行時間的測量。當然,為了提高時間的測量精度,MCU需要使用外部晶振來為其提供工作主頻。下面就對該方法進行詳細講解。該方法結合下面提到的開發(fā)板,可以達到10ns以內的測量分辨率和1us以內的測量精度。

1.2 測試平臺

這里使用的開發(fā)環(huá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
  • 本文對應的例程代碼鏈接如下。

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

1.3 使用STM32定時器測量程序執(zhí)行時間的方法詳解

這里就結合開發(fā)板STM32F429I-DISCO上的STM32F429ZI單片機來演示使用SysTick系統(tǒng)定時器測量程序代碼段執(zhí)行時間的實現(xiàn)方法。

使用SysTick系統(tǒng)定時器測量程序執(zhí)行時間之前,必須先確認定時器的以下參數(shù)。

  • 定時器的時鐘源頻率。
  • 定時器的定時周期。
  • 定時器的計數(shù)方向。

這里的代碼基于STM32F429I-DISCO開發(fā)板,該開發(fā)板的MCU外接8MHz的石英晶振,代碼使用該外部晶振經內部PLL倍頻后,產生168MHz的主頻供MCU使用。這里的SysTick系統(tǒng)定時器的時鐘源直接來自168MHz的主頻,對該頻率進行計數(shù),所以每過1000 / 168 = 5.95238ns時間,定時器計數(shù)值就會加1。這里將SysTick定時器的定時周期設置成1ms,即每過1ms,SysTick定時器就會產生一次定時器中斷。另外,SysTick定時器是倒計數(shù)定時器,即其計數(shù)值是遞減的,當計數(shù)值減到為0時,繼續(xù)減1時會重新加載重裝載值并繼續(xù)計時,同時產生定時器溢出中斷。

確定了以上參數(shù)之后,后面的代碼實現(xiàn)就非常簡單了,只需要實現(xiàn)以下的幾個功能函數(shù)皆可。

1)SysTick系統(tǒng)定時器初始化函數(shù)和中斷處理函數(shù)。用于配置該定時器的定時周期為1ms,打開定時器中斷并啟動定時,同時實現(xiàn)對應的中斷處理函數(shù)使定時器計數(shù)值累加。程序代碼如下。

// 該函數(shù)為STM32的官方代碼
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }


  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }


  /* Return function status */
  return HAL_OK;
}


// 該函數(shù)為STM32的官方代碼,調用的SysTick_Config()函數(shù)在“core_cm4.h”頭文件中有現(xiàn)成的實現(xiàn)
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}


// SysTick系統(tǒng)定時器中斷入口函數(shù)
void SysTick_Handler(void)
{
  HAL_IncTick();
}


// SysTick系統(tǒng)定時器中斷處理函數(shù),對uwTick值進行累加
__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}

2)獲取起始時間的函數(shù)。該函數(shù)用于獲取SysTick系統(tǒng)定時器當前的毫秒計數(shù)值,以及當前的定時器計數(shù)值。程序代碼如下。參數(shù)p_pdwStartMs為獲取到的起始毫秒計數(shù)值,p_pdwStartNsTicks為獲取到的起始定時器計數(shù)值。

void vGetStartTime(uint32_t* p_pdwStartMs, uint32_t* p_pdwStartNsTicks)
{
  *p_pdwStartMs = HAL_GetTick();
  *p_pdwStartNsTicks = SysTick->VAL;
}

3)獲取時間間隔的函數(shù)。該函數(shù)用于獲取當前時間相對于起始時間的時間間隔。程序代碼如下。參數(shù)p_dwStartMs為起始毫秒計數(shù)值,p_dwStartNsTicks為起始定時器計數(shù)值,p_pdwIntervalMs為當前時間相對于p_dwStartMs的毫秒時間間隔,p_pdwIntervalNsTicks為當前時間相對于p_dwStartNsTicks的定時器計數(shù)間隔。

void vGetIntervalTime(uint32_t p_dwStartMs, uint32_t p_dwStartNsTicks, uint32_t* p_pdwIntervalMs, uint32_t* p_pdwIntervalNsTicks)
{
  uint32_t l_dwCurMs = HAL_GetTick();
  uint32_t l_dwCurNsTicks = SysTick->VAL;
  uint32_t l_dwReloadValue = SysTick->LOAD;


  // STM32F429ZI的定時器為倒數(shù)定時器。
  // 如果當前的定時器計數(shù)值比起始計數(shù)值要小,SysTick未發(fā)生相對起始時刻不足1ms的定時器中斷,所以ms計數(shù)無需額外減1
  if(l_dwCurNsTicks <= p_dwStartNsTicks)
  {
    if(l_dwCurMs >= p_dwStartMs)
    {
      *p_pdwIntervalMs = l_dwCurMs - p_dwStartMs;
    }
    else
    {
      *p_pdwIntervalMs = ~(p_dwStartMs - l_dwCurMs) + 1;
    }
    *p_pdwIntervalNsTicks = p_dwStartNsTicks - l_dwCurNsTicks;
  }
  // 如果當前的定時器計數(shù)值比起始計數(shù)值要大,SysTick發(fā)生了相對起始時刻不足1ms的定時器中斷,所以ms計數(shù)需要額外減1
  else
  {
    if(l_dwCurMs >= p_dwStartMs)
    {
      *p_pdwIntervalMs = l_dwCurMs - p_dwStartMs - 1;
    }
    else
    {
      *p_pdwIntervalMs = ~(p_dwStartMs - l_dwCurMs);
    }
    *p_pdwIntervalNsTicks = p_dwStartNsTicks + (l_dwReloadValue - l_dwCurNsTicks) + 1;
  }
}

4)獲取程序代碼段執(zhí)行時間的演示例程。用于演示如何使用以上提到的相關函數(shù)來測量程序代碼段的執(zhí)行時間。

int main(void)
{
  uint32_t count = 0;
  uint32_t l_dwStartMs, l_dwIntervalMs;
  uint32_t l_dwStartNsTicks, l_dwIntervalNsTicks;
  float l_fUs;  // 微秒時間


  HAL_Init();


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


  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);


  vGetStartTime(&l_dwStartMs, &l_dwStartNsTicks);
#if 1
  while (1)
  {
    if (count == 0x3fffff)
    {
      BSP_LED_Toggle(LED3);
      BSP_LED_Toggle(LED4);
      count = 0;
      break;
    }
    count++;
  }
#else
  vDelayUs(1000);
#endif
  vGetIntervalTime(l_dwStartMs, l_dwStartNsTicks, &l_dwIntervalMs, &l_dwIntervalNsTicks);
  l_fUs = l_dwIntervalMs * 1000 + l_dwIntervalNsTicks * NS_PER_SYS_TICK / 1000.0f;


  while(1);
}

圖1 以上演示例程代碼段的執(zhí)行時間

1.4 結語

通過以上提到的相關函數(shù),可以很方便地實現(xiàn)程序執(zhí)行時間的測量,而且可以在幾乎任何地方使用(中斷內部使用需注意中斷優(yōu)先級的影響)。另外,如果結合串口打印調試信息的功能,可以直接將測量到的執(zhí)行時間直接打印輸出,方便查看。本文提到的執(zhí)行時間測量方法無需使用示波器,也不需要借用MCU的GPIO口進行輔助測量,使用起來非常方便。

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

    關注

    6030

    文章

    44489

    瀏覽量

    631994
  • 示波器
    +關注

    關注

    113

    文章

    6164

    瀏覽量

    184316
  • GPIO
    +關注

    關注

    16

    文章

    1188

    瀏覽量

    51836
  • 程序執(zhí)行時間

    關注

    0

    文章

    2

    瀏覽量

    6691
收藏 人收藏

    評論

    相關推薦

    如何使用STM模塊測量函數(shù)的執(zhí)行時間?

    我想問你如何使用 STM 模塊測量函數(shù)的執(zhí)行時間。 是否有可能通過BSP.H庫的now () 函數(shù)為兩個類型為ifx_tickTimer的變量(分別為起始變量和停止變量分配分筆數(shù))來通過BSP默認
    發(fā)表于 01-22 06:38

    LabVIEW 程序執(zhí)行架構——程序執(zhí)行時間控制

    程序執(zhí)行時間控制介紹在介紹時間控制元件之前,我們先來了解為什么程序需要控制時間。舉例來說,若我們想要做到每秒顯示出一張不一樣的圖片,那我們就
    發(fā)表于 12-26 11:38

    如何計算執(zhí)行時間

    嗨,大家好,有沒有方法計算程序程序的一部分(在兩個斷點之間)的執(zhí)行時間?比如秒表之類的?我希望任何人都能幫上忙!搶劫 以上來自于百度翻譯 以下為原文Hi all, Is there
    發(fā)表于 07-29 08:07

    如何在microblaze上測量C代碼的執(zhí)行時間?

    如何在microblaze上測量C代碼的執(zhí)行時間?沒有使用OS,所以我不能在time.h中使用桌面C函數(shù),我是否必須使用xps計時或axi計時?任何人都可以使用xps計時
    發(fā)表于 10-30 09:36

    如何使用CYCLECOUNTER快速的測量執(zhí)行時間

    系統(tǒng)基于該寄存實現(xiàn)了一個64位的循環(huán)周期計數(shù)CYCLECOUNTER,能夠精確的測量程序執(zhí)行時間,并且可以與C-SPY宏結合,成為開發(fā)人員非常有用的一個工具。CYCLECOUNT
    發(fā)表于 01-08 13:40

    如何在MCU上測量代碼執(zhí)行時間?

    期限(deadline)要求。測量部分代碼的實際執(zhí)行時間可以幫助我們找到代碼中的時間關鍵點。本文將展示如何輕松測量和顯示基于Cortex-M MCU的代碼片段的
    發(fā)表于 07-16 09:59

    STM32定時器的功能

    。(我這里配置了兩個定時器 TIM3 和tim4這里不說cube的使用方法了)tim3 我配置了10ms的定時。注意點一:定時器配置時間的時
    發(fā)表于 08-12 06:31

    STM32定時器詳解

    結合起來使用的話可以實現(xiàn)非常豐富的功能,可以測量輸入信號的脈沖寬度,可以生產輸出波形。定時器生產 PWM 控制電機狀態(tài)是工業(yè)控制普遍方法,這方面知識非常有必要深入了解。STM32F4
    發(fā)表于 08-18 06:17

    MPC5744p如何優(yōu)化程序執(zhí)行時間?

    作為 MPC5744p 的新手,我遇到了一個關于如何優(yōu)化程序執(zhí)行時間的問題。 這是我的中斷服務例程中代碼行的圖片。 ↓這張圖片顯示了執(zhí)行我測試過的代碼行之前的定時器值 ↓這張圖片顯示
    發(fā)表于 06-05 12:50

    stm32定時器中斷程序

    STM32定時器是個強大的模塊,定時器使用的頻率也是很高的,定時器可以做一些基本的定時,還可以做PWM輸出或者輸入捕獲功能。 以下是進行
    發(fā)表于 10-12 16:59 ?1.3w次閱讀

    如何用SysTick實現(xiàn)測量程序行時間

    在實際的項目開發(fā)過程中,常常遇到需要得到一段代碼的運行時間,通常的方法是用示波器來測量,這篇博文將用 SysTick 來實現(xiàn) 精確測量 程序
    的頭像 發(fā)表于 05-09 14:07 ?5992次閱讀
    如何用SysTick實現(xiàn)<b class='flag-5'>測量程序</b>運<b class='flag-5'>行時間</b>

    如何測量ARM Cortex-M MCU代碼的執(zhí)行時間

    期限(deadline)要求。測量部分代碼的實際執(zhí)行時間可以幫助我們找到代碼中的時間關鍵點。 本文將展示如何輕松測量和顯示基于Cortex-M MCU的代碼片段的
    的頭像 發(fā)表于 08-26 09:20 ?3564次閱讀
    如何<b class='flag-5'>測量</b>ARM Cortex-M MCU代碼的<b class='flag-5'>執(zhí)行時間</b>

    MCU上的代碼執(zhí)行時間

    編寫的,而且開發(fā)人員常常被迫對代碼進行手工優(yōu)化,可能會回到匯編語言,以滿足性能的需求。測量代碼部分的實際執(zhí)行時間可以幫助找到代碼中的熱點。本文將說明如何可以方便地測量和顯示在基于Cortex-M MCU的...
    發(fā)表于 10-28 13:36 ?12次下載
    MCU上的代碼<b class='flag-5'>執(zhí)行時間</b>

    STM32F407+CubeMX - 使用GPIO翻轉+示波器測量函數(shù)的執(zhí)行時間

    + 斷點的方式可以測量某個函數(shù)的運行時間。所以,測量的前提是你用Keil軟件作為嵌入式開發(fā)的IDE,其他IDE就不適用了。這里使用硬件的方式來測量某個函數(shù)的運
    發(fā)表于 12-05 12:36 ?9次下載
    <b class='flag-5'>STM32</b>F407+CubeMX - 使用GPIO翻轉+示波器<b class='flag-5'>測量</b>函數(shù)的<b class='flag-5'>執(zhí)行時間</b>

    TPT19新特性之最壞情況執(zhí)行時間的指示

    主機上的執(zhí)行時間。 指示顯示了哪些測試和哪些測試刺激延長了執(zhí)行時間。因此,您可以使用指示作為代碼變更的早期預警系統(tǒng)推導出測量目標板上真
    的頭像 發(fā)表于 04-27 10:08 ?446次閱讀
    TPT19新特性之最壞情況<b class='flag-5'>執(zhí)行時間</b>的指示