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

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

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

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

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

1.1 背景

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

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

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/85162425

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

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

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

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

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

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

1)SysTick系統(tǒng)定時(shí)器初始化函數(shù)和中斷處理函數(shù)。用于配置該定時(shí)器的定時(shí)周期為1ms,打開定時(shí)器中斷并啟動定時(shí),同時(shí)實(shí)現(xiàn)對應(yīng)的中斷處理函數(shù)使定時(shí)器計(jì)數(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的官方代碼,調(diào)用的SysTick_Config()函數(shù)在“core_cm4.h”頭文件中有現(xiàn)成的實(shí)現(xiàn)
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}


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


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

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

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

3)獲取時(shí)間間隔的函數(shù)。該函數(shù)用于獲取當(dāng)前時(shí)間相對于起始時(shí)間的時(shí)間間隔。程序代碼如下。參數(shù)p_dwStartMs為起始毫秒計(jì)數(shù)值,p_dwStartNsTicks為起始定時(shí)器計(jì)數(shù)值,p_pdwIntervalMs為當(dāng)前時(shí)間相對于p_dwStartMs的毫秒時(shí)間間隔,p_pdwIntervalNsTicks為當(dāng)前時(shí)間相對于p_dwStartNsTicks的定時(shí)器計(jì)數(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í)器。
  // 如果當(dāng)前的定時(shí)器計(jì)數(shù)值比起始計(jì)數(shù)值要小,SysTick未發(fā)生相對起始時(shí)刻不足1ms的定時(shí)器中斷,所以ms計(jì)數(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;
  }
  // 如果當(dāng)前的定時(shí)器計(jì)數(shù)值比起始計(jì)數(shù)值要大,SysTick發(fā)生了相對起始時(shí)刻不足1ms的定時(shí)器中斷,所以ms計(jì)數(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í)間的演示例程。用于演示如何使用以上提到的相關(guān)函數(shù)來測量程序代碼段的執(zhí)行時(shí)間。

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


  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í)行時(shí)間

1.4 結(jié)語

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

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

    關(guān)注

    6037

    文章

    44558

    瀏覽量

    635355
  • 示波器
    +關(guān)注

    關(guān)注

    113

    文章

    6246

    瀏覽量

    184963
  • GPIO
    +關(guān)注

    關(guān)注

    16

    文章

    1204

    瀏覽量

    52104
  • 程序執(zhí)行時(shí)間

    關(guān)注

    0

    文章

    2

    瀏覽量

    6699
收藏 人收藏

    評論

    相關(guān)推薦

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

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

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

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

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

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

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

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

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

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

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

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

    STM32定時(shí)器的功能

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

    STM32定時(shí)器詳解

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

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

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

    stm32定時(shí)器中斷程序

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

    如何用SysTick實(shí)現(xiàn)測量程序運(yùn)行時(shí)間

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

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

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

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

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

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

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

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

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