如何測量代碼運行時間


01、示波器

測量一段代碼運行時間第一時間想到的當然是示波器了,在測量開始的代碼前面拉高某個GPIO,在結束測量的位置拉低這個GPIO,直接使用示波器查看這個GPIO的高電平時間長度即可,就是我們要測量的這段代碼的運行時間。

那么直接上示例,為了模擬代碼運行一段時間,這里我直接采用之前文章《STM32的四種延時方法》直接延時。

  while (1)
  {
    GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄滅LED燈                     
    delay_ms(500);//延時500ms
    GPIO_ResetBits(GPIOE,GPIO_Pin_4);//點亮LED燈                     
    delay_ms(500);//延時500ms
  }

延時500ms時波形如下

圖片

當修改代碼,延時100ms時

  while (1)
  {
    GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄滅LED燈                     
    delay_ms(100);//延時100ms
    GPIO_ResetBits(GPIOE,GPIO_Pin_4);//點亮LED燈                     
    delay_ms(100);//延時100ms
  }

波形如下

圖片

測量准確無誤,但是他的缺點也很明顯啊,需要示波器,示波器一般很笨重的,即使是輕便的示波器,也需要接硬件,還是很麻煩的,而且需要一個空閑的GPIO,測量的這段代碼中,不能使用到這個GPIO。

02、定時器測量

定時器不僅僅我們可以實現我們之前講解的《基礎定時功能》《PWM輸出功能》《輸入捕獲功能》《觸摸按鍵功能》,還可以用於測量一段代碼的運行時間。在學習使用定時器測量代碼運行時間之前,如果對定時器不了解的同學先看剛剛提到的定時器的文中,重點文章《STM32基礎定時器簡介》。本篇文章不再講解定時器的基礎功能。

定時器本質上就是向上累加的計數器(如果配置成向上計數時),所以我們在測量開始的代碼前面讀取定時器的計數器,在結束測量的位置再讀取定時器的計數器,獲得兩次的差值,這樣就可以計算出這段代碼的運行的時間。這就是簡單的原理,下面直接擼代碼。

首先配置定時器,這里我使用定時器3,配置定時器的計數器每增加1,表示100us。並且將溢出值設置為最大。

void TIM_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF-1;
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock / 2) / 10000) - 1;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  TIM_Cmd(TIM3, ENABLE);
}

測量代碼運行時間的代碼如下,這里進行了防溢出的處理

  while (1)
  {
    GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄滅LED燈                     
    delay_ms(100);//延時100ms
    GPIO_ResetBits(GPIOE,GPIO_Pin_4);//點亮LED燈
    old_counter = TIM_GetCounter(TIM3);
    delay_ms(100);//延時100ms
    couter_current = TIM_GetCounter(TIM3);
    if(couter_current > old_counter)
      counter = couter_current - old_counter;
    else
      counter = couter_current + 0XFFFF - old_counter;
    time_ms = counter / 10;
  }

上述代碼延時100ms,通過定時器測量結果同樣為100ms,准確無誤。如下所示:

圖片

這樣有的同學可能已經聯想到了,上述代碼完全可以封裝成一個函數如下
float Time_Difference_ms(void)
{
  static uint32_t old_counter;
  uint32_t counter,couter_current;
  couter_current = TIM_GetCounter(TIM3);
  if(couter_current > old_counter)
    counter = couter_current - old_counter;
  else
    counter = couter_current + 0XFFFF - old_counter;
  old_counter = couter_current;
  return (counter / 10);
}

這樣就可以實現,測量兩次調用這個接口的是時間差,如下,可以准確測得兩次調用Time_Difference_ms這個函數的時間差是100ms。

圖片

上述代碼經過封裝,可以測量代碼兩次運行到相同位置的時間差。將程序再進化一下
float Time_Difference_ms(uint8_t flg)
{
  static uint32_t old_counter[5];
  uint32_t counter,couter_current;
  couter_current = TIM_GetCounter(TIM3);
  if(couter_current > old_counter[flg])
    counter = couter_current - old_counter[flg];
  else
    counter = couter_current + 0XFFFF - old_counter[flg];
  old_counter[flg] = couter_current;
  return (counter / 10);
}

這樣就可以得到多個位置兩次運行到相同位置的時間差。

當然,這樣也存在缺點:

1、需要占用一個定時器

2、按上述配置,最長測量時間為0XFFFF*0.1=6553.5ms=6.553.5s。

 

KeilIAR的工程文件下載地址:

PCB和工程代碼開源地址:

https://github.com/strongercjd/STM32F207VCT6

 

點擊查看本文所在的專輯,STM32F207教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM