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

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

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

    簡(jiǎn)析如何獲取單片機(jī)代碼運(yùn)行時(shí)間的方法

    GReq_mcu168 ? 來(lái)源:博客園 ? 作者:amanlikethis ? 2021-04-20 11:11 ? 次閱讀

    前言

    單片機(jī)編程者需要知道自己的程序需要花費(fèi)多長(zhǎng)時(shí)間、while周期是多少、delay延時(shí)是否真如函數(shù)功能描述那樣精確延時(shí)。

    很多時(shí)候,我們想知道這些參數(shù),但是由于懶惰或者沒(méi)有簡(jiǎn)單的辦法,將這件事推到“明天”。筆者提出了一種簡(jiǎn)便的測(cè)試方法,可以解決這些問(wèn)題。

    測(cè)試代碼的運(yùn)行時(shí)間的兩種方法:

    使用單片機(jī)內(nèi)部定時(shí)器,在待測(cè)程序段的開始啟動(dòng)定時(shí)器,在待測(cè)程序段的結(jié)尾關(guān)閉定時(shí)器。為了測(cè)量的準(zhǔn)確性,要進(jìn)行多次測(cè)量,并進(jìn)行平均取值。

    借助示波器的方法是:在待測(cè)程序段的開始階段使單片機(jī)的一個(gè)GPIO輸出高電平,在待測(cè)程序段的結(jié)尾階段再令這個(gè)GPIO輸出低電平。用示波器通過(guò)檢查高電平的時(shí)間長(zhǎng)度,就知道了這段代碼的運(yùn)行時(shí)間。顯然,借助于示波器的方法更為簡(jiǎn)便。

    以下內(nèi)容為這兩種方案的實(shí)例,以STM32為測(cè)試平臺(tái)。如果讀者是在另外的硬件平臺(tái)上測(cè)試,實(shí)際也不難,思路都是一樣的,自己可以編寫對(duì)應(yīng)的測(cè)試代碼。

    借助示波器方法的實(shí)例

    Delay_us函數(shù)使用STM32系統(tǒng)滴答定時(shí)器實(shí)現(xiàn):

    #include “systick.h”

    /* SystemFrequency / 1000 1ms中斷一次

    * SystemFrequency / 100000 10us中斷一次

    * SystemFrequency / 1000000 1us中斷一次

    */

    #define SYSTICKPERIOD 0.000001

    #define SYSTICKFREQUENCY (1/SYSTICKPERIOD)

    /**

    * @brief 讀取SysTick的狀態(tài)位COUNTFLAG

    * @param 無(wú)

    * @retval The new state of USART_FLAG (SET or RESET)。

    */

    static FlagStatus SysTick_GetFlagStatus(void)

    {

    if(SysTick-》CTRL&SysTick_CTRL_COUNTFLAG_Msk)

    {

    return SET;

    }

    else

    {

    return RESET;

    }

    }

    /**

    * @brief 配置系統(tǒng)滴答定時(shí)器 SysTick

    * @param 無(wú)

    * @retval 1 = failed, 0 = successful

    */

    uint32_t SysTick_Init(void)

    {

    /* 設(shè)置定時(shí)周期為1us */

    if (SysTick_Config(SystemCoreClock / SYSTICKFREQUENCY))

    {

    /* Capture error */

    return (1);

    }

    /* 關(guān)閉滴答定時(shí)器且禁止中斷 */

    SysTick-》CTRL &= ~ (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);

    return (0);

    }

    /**

    * @brief us延時(shí)程序,10us為一個(gè)單位

    * @param

    * @arg nTime: Delay_us( 10 ) 則實(shí)現(xiàn)的延時(shí)為 10 * 1us = 10us

    * @retval 無(wú)

    */

    void Delay_us(__IO uint32_t nTime)

    {

    /* 清零計(jì)數(shù)器并使能滴答定時(shí)器 */

    SysTick-》VAL = 0;

    SysTick-》CTRL |= SysTick_CTRL_ENABLE_Msk;

    for( ; nTime 》 0 ; nTime--)

    {

    /* 等待一個(gè)延時(shí)單位的結(jié)束 */

    while(SysTick_GetFlagStatus() != SET);

    }

    /* 關(guān)閉滴答定時(shí)器 */

    SysTick-》CTRL &= ~ SysTick_CTRL_ENABLE_Msk;

    }

    檢驗(yàn)Delay_us執(zhí)行時(shí)間中用到的GPIO(gpio.h、gpio.c)的配置:

    #ifndef __GPIO_H

    #define __GPIO_H

    #include “stm32f10x.h”

    #define LOW 0

    #define HIGH 1

    /* 帶參宏,可以像內(nèi)聯(lián)函數(shù)一樣使用 */

    #define TX(a) if (a)

    GPIO_SetBits(GPIOB,GPIO_Pin_0);

    else

    GPIO_ResetBits(GPIOB,GPIO_Pin_0)

    void GPIO_Config(void);

    #endif

    #include “gpio.h”

    /**

    * @brief 初始化GPIO

    * @param 無(wú)

    * @retval 無(wú)

    */

    void GPIO_Config(void)

    {

    /*定義一個(gè)GPIO_InitTypeDef類型的結(jié)構(gòu)體*/

    GPIO_InitTypeDef GPIO_InitStructure;

    /*開啟LED的外設(shè)時(shí)鐘*/

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    }

    在main函數(shù)中檢驗(yàn)Delay_us的執(zhí)行時(shí)間:

    #include “systick.h”

    #include “gpio.h”

    /**

    * @brief 主函數(shù)

    * @param 無(wú)

    * @retval 無(wú)

    */

    int main(void)

    {

    GPIO_Config();

    /* 配置SysTick定時(shí)周期為1us */

    SysTick_Init();

    for(;;)

    {

    TX(HIGH);

    Delay_us(1);

    TX(LOW);

    Delay_us(100);

    }

    }

    示波器的觀察結(jié)果

    可見Delay_us(100),執(zhí)行了大概102us,而Delay_us(1)執(zhí)行了2.2us。

    更改一下main函數(shù)的延時(shí)參數(shù):

    int main(void)

    {

    /* LED 端口初始化 */

    GPIO_Config();

    /* 配置SysTick定時(shí)周期為1us */

    SysTick_Init();

    for(;;)

    {

    TX(HIGH);

    Delay_us(10);

    TX(LOW);

    Delay_us(100);

    }

    }

    示波器的觀察結(jié)果:

    可見Delay_us(100),執(zhí)行了大概101us,而Delay_us(10)執(zhí)行了11.4us。

    結(jié)論:此延時(shí)函數(shù)基本上還是可靠的。

    使用定時(shí)器方法的實(shí)例

    至于使用定時(shí)器方法,軟件檢測(cè)程序段的執(zhí)行時(shí)間,程序?qū)崿F(xiàn)思路見STM32之系統(tǒng)滴答定時(shí)器:

    http://www.cnblogs.com/amanlikethis/p/3730205.html

    筆者已經(jīng)將檢查軟件的使用封裝成庫(kù),使用方法在鏈接文章中也有介紹。我們這里只做一下簡(jiǎn)要的實(shí)踐活動(dòng)。

    Delay_us函數(shù)使用STM32定時(shí)器2實(shí)現(xiàn):

    #include “timer.h”

    /* SystemFrequency / 1000 1ms中斷一次

    * SystemFrequency / 100000 10us中斷一次

    * SystemFrequency / 1000000 1us中斷一次

    */

    #define SYSTICKPERIOD 0.000001

    #define SYSTICKFREQUENCY (1/SYSTICKPERIOD)

    /**

    * @brief 定時(shí)器2的初始化,,定時(shí)周期1uS

    * @param 無(wú)

    * @retval 無(wú)

    */

    void TIM2_Init(void)

    {

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    /*AHB = 72MHz,RCC_CFGR的PPRE1 = 2,所以APB1 = 36MHz,TIM2CLK = APB1*2 = 72MHz */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    /* Time base configuration */

    TIM_TimeBaseStructure.TIM_Period = SystemCoreClock/SYSTICKFREQUENCY -1;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ARRPreloadConfig(TIM2, ENABLE);

    /* 設(shè)置更新請(qǐng)求源只在計(jì)數(shù)器上溢或下溢時(shí)產(chǎn)生中斷 */

    TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Global);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    }

    /**

    * @brief us延時(shí)程序,10us為一個(gè)單位

    * @param

    * @arg nTime: Delay_us( 10 ) 則實(shí)現(xiàn)的延時(shí)為 10 * 1us = 10us

    * @retval 無(wú)

    */

    void Delay_us(__IO uint32_t nTime)

    {

    /* 清零計(jì)數(shù)器并使能滴答定時(shí)器 */

    TIM2-》CNT = 0;

    TIM_Cmd(TIM2, ENABLE);

    for( ; nTime 》 0 ; nTime--)

    {

    /* 等待一個(gè)延時(shí)單位的結(jié)束 */

    while(TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != SET);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    }

    TIM_Cmd(TIM2, DISABLE);

    }

    在main函數(shù)中檢驗(yàn)Delay_us的執(zhí)行時(shí)間:

    #include “stm32f10x.h”

    #include “Timer_Drive.h”

    #include “gpio.h”

    #include “systick.h”

    TimingVarTypeDef Time;

    int main(void)

    {

    TIM2_Init();

    SysTick_Init();

    SysTick_Time_Init(&Time);

    for(;;)

    {

    SysTick_Time_Start();

    Delay_us(1000);

    SysTick_Time_Stop();

    }

    }

    怎么去看檢測(cè)結(jié)果呢?用調(diào)試的辦法,打開調(diào)試界面后,將Time變量添加到Watch一欄中。然后全速運(yùn)行程序,既可以看到Time中保存變量的變化情況,其中TimeWidthAvrage就是最終的結(jié)果。

    可以看到TimeWidthAvrage的值等于0x119B8,十進(jìn)制數(shù)對(duì)應(yīng)72120,滴答定時(shí)器的一個(gè)滴答為1/72M(s),所以Delay_us(1000)的執(zhí)行時(shí)間就是72120*1/72M (s) = 0.001001s,也就是1ms。驗(yàn)證成功。

    備注:定時(shí)器方法輸出檢測(cè)結(jié)果有待改善,你可以把得到的TimeWidthAvrage轉(zhuǎn)換成時(shí)間(以u(píng)s、ms、s)為單位,然后通過(guò)串口打印出來(lái),不過(guò)這部分工作對(duì)于經(jīng)常使用調(diào)試的人員來(lái)說(shuō)也可有可無(wú)。

    兩種方法對(duì)比

    軟件測(cè)試方法:

    操作起來(lái)復(fù)雜,由于在原代碼基礎(chǔ)上增加了測(cè)試代碼,可能會(huì)影響到原代碼的工作,測(cè)試可靠性相對(duì)較低。由于使用32位的變量保存systick的計(jì)數(shù)次數(shù),計(jì)時(shí)的最大長(zhǎng)度可以達(dá)到2^32/72M = 59.65 s。

    示波器方法

    操作簡(jiǎn)單,在原代碼基礎(chǔ)上幾乎沒(méi)有增加代碼,測(cè)試可靠性很高。由于示波器的顯示能力有限,超過(guò)1s以上的程序段,計(jì)時(shí)效果不是很理想。但是,通常的單片機(jī)程序?qū)崟r(shí)性要求很高,一般不會(huì)出現(xiàn)程序段時(shí)間超過(guò)秒級(jí)的情況。

    綜合對(duì)比,推薦使用示波器方法。

    編輯:jq

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

      關(guān)注

      6039

      文章

      44579

      瀏覽量

      636452
    • 定時(shí)器
      +關(guān)注

      關(guān)注

      23

      文章

      3251

      瀏覽量

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

      關(guān)注

      3

      文章

      4338

      瀏覽量

      62747

    原文標(biāo)題:實(shí)用 | 獲取單片機(jī)代碼運(yùn)行時(shí)間的方法

    文章出處:【微信號(hào):mcu168,微信公眾號(hào):硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

    收藏 人收藏

      評(píng)論

      相關(guān)推薦

      ups主機(jī)選購(gòu)方法,選擇電池運(yùn)行時(shí)間滿足

      時(shí),應(yīng)考慮以下幾個(gè)因素:能力確定要連接到UPS的設(shè)備的電源要求。選擇具有足夠容量的UPS,以在所需的持續(xù)時(shí)間內(nèi)處理負(fù)載。電池運(yùn)行時(shí)間考慮在停電期間需要UPS供電多長(zhǎng)時(shí)間
      的頭像 發(fā)表于 12-06 09:28 ?148次閱讀
      ups主機(jī)選購(gòu)<b class='flag-5'>方法</b>,選擇電池<b class='flag-5'>運(yùn)行時(shí)間</b>滿足

      如何寫出穩(wěn)定的單片機(jī)代碼

      。 ? ? ? ? ? 對(duì)于單片機(jī)產(chǎn)品來(lái)說(shuō),高效可能不是剛需。 ? ? ? ? ? 高效寫法和低效寫法,在很多功能上看不出區(qū)別,代碼執(zhí)行效率快個(gè)納秒、微秒、甚至是毫秒的時(shí)間差,對(duì)功能本身并無(wú)影響。 ? ? ? ? ? 所以在高效
      的頭像 發(fā)表于 11-15 16:40 ?433次閱讀
      如何寫出穩(wěn)定的<b class='flag-5'>單片機(jī)</b><b class='flag-5'>代碼</b>

      影響逆變器電池狀態(tài)的原因,整體運(yùn)行時(shí)間

      逆變器的使用需要了解影響電池性能和整體運(yùn)行時(shí)間的因素。讓我們深入探討最大化電源設(shè)置的關(guān)鍵考慮因素。逆變器效率:逆變器的效率至關(guān)重要。當(dāng)逆變器將電池的DC電能轉(zhuǎn)換為交流
      的頭像 發(fā)表于 10-18 10:41 ?323次閱讀
      影響逆變器電池狀態(tài)的原因,整體<b class='flag-5'>運(yùn)行時(shí)間</b>

      C2000?MCU的運(yùn)行時(shí)堆棧大小監(jiān)測(cè)

      電子發(fā)燒友網(wǎng)站提供《C2000?MCU的運(yùn)行時(shí)堆棧大小監(jiān)測(cè).pdf》資料免費(fèi)下載
      發(fā)表于 09-11 09:30 ?0次下載
      C2000?MCU的<b class='flag-5'>運(yùn)行時(shí)</b>堆棧大小監(jiān)測(cè)

      單片機(jī)燒錄程序的線比單片機(jī)上的少還能燒錄嗎

      的存儲(chǔ)器通常分為兩類:ROM(只讀存儲(chǔ)器)和RAM(隨機(jī)存取存儲(chǔ)器)。ROM用于存儲(chǔ)程序代碼,而RAM用于存儲(chǔ)程序運(yùn)行過(guò)程中的數(shù)據(jù)。燒錄過(guò)程就是將程序代碼寫入ROM中。 單片機(jī)燒錄
      的頭像 發(fā)表于 09-02 09:54 ?534次閱讀

      單片機(jī)程序燒錄成功為什么不運(yùn)行

      電壓波動(dòng)。 復(fù)位問(wèn)題 : 檢查單片機(jī)是否有正確的復(fù)位信號(hào)。 確認(rèn)復(fù)位電路是否正常工作。 晶振/時(shí)鐘問(wèn)題 : 確保單片機(jī)的外部晶振或時(shí)鐘源工作正常。 檢查晶振是否與單片機(jī)兼容。 代碼問(wèn)題
      的頭像 發(fā)表于 09-02 09:45 ?2320次閱讀

      三菱plc累計(jì)運(yùn)行時(shí)間怎么編程

      具有重要意義。本文將詳細(xì)介紹如何使用三菱PLC編程實(shí)現(xiàn)累計(jì)運(yùn)行時(shí)間的統(tǒng)計(jì)功能。 一、概述 累計(jì)運(yùn)行時(shí)間是指設(shè)備或系統(tǒng)在一定時(shí)間內(nèi)的總運(yùn)行時(shí)間。在工業(yè)生產(chǎn)中,對(duì)設(shè)備的累計(jì)
      的頭像 發(fā)表于 06-20 11:31 ?2371次閱讀

      變頻器帶動(dòng)電機(jī)運(yùn)行時(shí)發(fā)抖的原因及處理方法

      不良影響。因此,深入了解變頻器帶動(dòng)電機(jī)運(yùn)行時(shí)發(fā)抖的原因,并采取相應(yīng)的處理方法,對(duì)于確保電機(jī)穩(wěn)定、高效運(yùn)行具有重要意義。
      的頭像 發(fā)表于 05-31 14:43 ?5806次閱讀

      STM8S在IAR軟件仿真Simulator怎么查看運(yùn)行時(shí)間?

      STM8S 在IAR軟件仿真Simulator怎么查看運(yùn)行時(shí)間?在某些芯片通信時(shí),會(huì)要求延時(shí)5us,10us,150ms等,這些延時(shí)不需要太精確,只要大概就好,但怎么在Simulator仿真里能通過(guò)斷點(diǎn)查看,即兩個(gè)斷點(diǎn)之間的運(yùn)行時(shí)間呢? 除了通過(guò)IO輸出外圍用儀器測(cè)試,能
      發(fā)表于 05-09 07:48

      stm32cubeIDE代碼運(yùn)行時(shí)間如何查看?

      stm32cubeIDE 代碼運(yùn)行時(shí)間,如何查看?就如 keil 調(diào)試時(shí)候那樣,可以測(cè)試代碼運(yùn)行時(shí)間。但是在stm32cubeIDE 中,一直沒(méi)有找到這個(gè)功能,不知道哪位高人可以提示
      發(fā)表于 04-16 08:10

      stm32做https的server ,serverkeychange運(yùn)行時(shí)間10多s怎么優(yōu)化?

      stm32做https的server ,serverkeychange這一步運(yùn)行時(shí)間10多s,求優(yōu)化辦法
      發(fā)表于 03-27 08:03

      【鴻蒙】OpenHarmony 4.0藍(lán)牙代碼結(jié)構(gòu)簡(jiǎn)

      OpenHarmony 4.0藍(lán)牙代碼結(jié)構(gòu)簡(jiǎn)前言 OpenHarmony 4.0上藍(lán)牙倉(cāng)和目錄結(jié)構(gòu)進(jìn)行一次較大整改,本文基于4.0以上版本對(duì)藍(lán)牙代碼進(jìn)行分析,便于讀者快速了解和學(xué)習(xí)
      的頭像 發(fā)表于 02-26 16:08 ?1610次閱讀
      【鴻蒙】OpenHarmony 4.0藍(lán)牙<b class='flag-5'>代碼</b>結(jié)構(gòu)<b class='flag-5'>簡(jiǎn)</b><b class='flag-5'>析</b>

      如何在運(yùn)行時(shí)計(jì)算設(shè)計(jì)中使用的時(shí)鐘頻率?

      我想知道如何在運(yùn)行時(shí)計(jì)算設(shè)計(jì)中使用的時(shí)鐘頻率(設(shè)計(jì)使用時(shí)鐘組件),尤其是組件內(nèi)部的時(shí)鐘,例如 UART。 例如,使用 clock_getSourceRegister () 返回
      發(fā)表于 01-24 06:09

      如何在運(yùn)行時(shí)擦除/編程UCB?

      我有一個(gè)項(xiàng)目需要在現(xiàn)場(chǎng)更新 SOTA。 這需要在運(yùn)行時(shí)更新必要的 UCB 值。 我已經(jīng)看過(guò)擦除/編程 PFLASH 和 DFLASH 的示例代碼,但我還沒(méi)有找到任何特定于 UCB 內(nèi)存的代碼。 我
      發(fā)表于 01-22 07:18

      請(qǐng)問(wèn)M480系列的MCU可以獲取單次上電的CLK運(yùn)行時(shí)長(zhǎng)嗎?

      請(qǐng)問(wèn)M480系列的MCU,可以獲取單次上電的CLK運(yùn)行時(shí)長(zhǎng)嗎? 例如 設(shè)定一個(gè)變量,long 型的,記錄自上電的運(yùn)行時(shí)長(zhǎng)。謝謝!
      發(fā)表于 01-16 07:38