在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

3天內不再提示

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

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

1.1 背景

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

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

1.2 測試平臺

這里使用的開發環境和相關硬件如下。

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

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

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

這里就結合開發板STM32F429I-DISCO上的STM32F429ZI單片機來演示使用SysTick系統定時器測量程序代碼段執行時間的實現方法。

使用SysTick系統定時器測量程序執行時間之前,必須先確認定時器的以下參數

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

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

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

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

// 該函數為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;
}


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


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


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

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

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

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

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的定時器為倒數定時器。
  // 如果當前的定時器計數值比起始計數值要小,SysTick未發生相對起始時刻不足1ms的定時器中斷,所以ms計數無需額外減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;
  }
  // 如果當前的定時器計數值比起始計數值要大,SysTick發生了相對起始時刻不足1ms的定時器中斷,所以ms計數需要額外減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)獲取程序代碼段執行時間的演示例程。用于演示如何使用以上提到的相關函數來測量程序代碼段的執行時間。

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 以上演示例程代碼段的執行時間

1.4 結語

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

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

    關注

    6043

    文章

    44621

    瀏覽量

    638574
  • 示波器
    +關注

    關注

    113

    文章

    6282

    瀏覽量

    185843
  • GPIO
    +關注

    關注

    16

    文章

    1216

    瀏覽量

    52380
  • 程序執行時間

    關注

    0

    文章

    2

    瀏覽量

    6709
收藏 人收藏

    評論

    相關推薦

    如何使用STM模塊測量函數的執行時間

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

    LabVIEW 程序執行架構——程序執行時間控制

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

    如何計算執行時間

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

    如何在microblaze上測量C代碼的執行時間

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

    如何使用CYCLECOUNTER快速的測量執行時間

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

    如何在MCU上測量代碼執行時間

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

    STM32定時器的功能

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

    STM32定時器詳解

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

    MPC5744p如何優化程序執行時間?

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

    stm32定時器中斷程序

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

    如何用SysTick實現測量程序行時間

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

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

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

    MCU上的代碼執行時間

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

    STM32F407+CubeMX - 使用GPIO翻轉+示波器測量函數的執行時間

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

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

    主機上的執行時間。 指示顯示了哪些測試和哪些測試刺激延長了執行時間。因此,您可以使用指示作為代碼變更的早期預警系統推導出測量目標板上真
    的頭像 發表于 04-27 10:08 ?519次閱讀
    TPT19新特性之最壞情況<b class='flag-5'>執行時間</b>的指示
    主站蜘蛛池模板: 久久福利免费视频 | 人人看人人看人做人人模 | 日本加勒比高清一本大道 | 另类free性欧美护士 | 国产一级aaa全黄毛片 | 亚洲一级毛片免费在线观看 | 日本三级在线 | 中文字幕一区二区三区 精品 | 一级片在线免费观看 | 一区二区影院 | 日本亚洲欧美美色 | 四虎国产视频 | 永久免费看mv网站入口 | 欧美黄色大片免费观看 | 久久精品国产99久久72 | 高清午夜线观看免费 | 日本一本高清视频 | 国产www在线播放 | 丁香婷婷社区 | 国产一区美女 | 亚洲成人在线网站 | 久久久夜 | 青草99 | 中文字幕亚洲一区 | 婷婷丁香视频 | 日日操免费视频 | 天堂bt资源新版在线 | 久久综合九色综合网站 | 99久久精品费精品国产一区二区 | 天天操天天干天天爽 | 国产在线黄 | 欧美特级黄| 久久青草视频 | h视频免费在线 | 奇米4色| 2017天天干夜夜操 | 国产伦精品一区二区三区四区 | 国产欧美日韩在线人成aaaa | 91精品久久国产青草 | 69xxx日本护士| 日本边添边爱边摸边做边爱 |