0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

浅析STM32代码运行时间的技巧

STM32嵌入式开发 来源:STM32嵌入式开发 作者:STM32嵌入式开发 2021-11-09 09:52 次阅读

前言

测试代码的运行时间的两种方法:

  • 使用单片机内部定时器,在待测程序段的开始启动定时器,在待测程序段的结尾关闭定时器。为了测量的准确性,要进行多次测量,并进行平均取值。

  • 借助示波器的方法是:在待测程序段的开始阶段使单片机的一个GPIO输出高电平,在待测程序段的结尾阶段再令这个GPIO输出低电平。用示波器通过检查高电平的时间长度,就知道了这段代码的运行时间。显然,借助于示波器的方法更为简便。

借助示波器方法的实例

Delay_us函数使用STM32系统滴答定时器实现:

#include "systick.h"
/* SystemFrequency / 1000    1ms中断一次 * SystemFrequency / 100000     10us中断一次 * SystemFrequency / 1000000 1us中断一次 */
#define SYSTICKPERIOD                    0.000001#define SYSTICKFREQUENCY            (1/SYSTICKPERIOD)
/**  * @brief  读取SysTick的状态位COUNTFLAG  * @param  * @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  配置系统滴答定时器 SysTick  * @param  无  * @retval 1 = failed, 0 = successful  */uint32_t SysTick_Init(void){/* 设置定时周期为1us  */if (SysTick_Config(SystemCoreClock / SYSTICKFREQUENCY))     { /* Capture error */return (1);    }
/* 关闭滴答定时器且禁止中断  */    SysTick->CTRL &= ~ (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);                                                  return (0);}
/**  * @brief   us延时程序,10us为一个单位  * @param  *        @arg nTime: Delay_us( 10 ) 则实现的延时为 10 * 1us = 10us  * @retval  无  */void Delay_us(__IO uint32_t nTime){     /* 清零计数器并使能滴答定时器 */    SysTick->VAL   = 0;      SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;     
for( ; nTime > 0 ; nTime--)    {/* 等待一个延时单位的结束 */while(SysTick_GetFlagStatus() != SET);    }
/* 关闭滴答定时器 */    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;}

检验Delay_us执行时间中用到的GPIO(gpio.h、gpio.c)的配置:


		
#ifndef __GPIO_H#define    __GPIO_H
#include "stm32f10x.h"
#define     LOW          0#define     HIGH         1
/* 带参宏,可以像内联函数一样使用 */#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  无  * @retval 无  */void GPIO_Config(void){        /*定义一个GPIO_InitTypeDef类型的结构体*/        GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED的外设时钟*/        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函数中检验Delay_us的执行时间:

dce66dd8-3fbe-11ec-9195-dac502259ad0.png

示波器的观察结果:

dd590280-3fbe-11ec-9195-dac502259ad0.png

dd8a5a10-3fbe-11ec-9195-dac502259ad0.png

可见Delay_us(100),执行了大概102us,而Delay_us(1)执行了2.2us。

更改一下main函数的延时参数

ddbb944a-3fbe-11ec-9195-dac502259ad0.png

示波器的观察结果:

de23e14e-3fbe-11ec-9195-dac502259ad0.png

de616afa-3fbe-11ec-9195-dac502259ad0.png

可见Delay_us(100),执行了大概101us,而Delay_us(10)执行了11.4us。

结论:此延时函数基本上还是可靠的。

使用定时器方法的实例

Delay_us函数使用STM32定时器2实现:

#include "timer.h"
/* SystemFrequency / 1000            1ms中断一次 * SystemFrequency / 100000     10us中断一次 * SystemFrequency / 1000000         1us中断一次 */
#define SYSTICKPERIOD                    0.000001#define SYSTICKFREQUENCY            (1/SYSTICKPERIOD)
/**  * @brief  定时器2的初始化,,定时周期1uS  * @param  无  * @retval 无  */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);
/* 设置更新请求源只在计数器上溢或下溢时产生中断 */    TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Global);     TIM_ClearFlag(TIM2, TIM_FLAG_Update);}
/**  * @brief   us延时程序,10us为一个单位  * @param    *        @arg nTime: Delay_us( 10 ) 则实现的延时为 10 * 1us = 10us  * @retval  无  */void Delay_us(__IO uint32_t nTime){     /* 清零计数器并使能滴答定时器 */    TIM2->CNT   = 0;      TIM_Cmd(TIM2, ENABLE);     
for( ; nTime > 0 ; nTime--)    {/* 等待一个延时单位的结束 */while(TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != SET);     TIM_ClearFlag(TIM2, TIM_FLAG_Update);    }
    TIM_Cmd(TIM2, DISABLE);}

在main函数中检验Delay_us的执行时间:

#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();    }     }

怎么去看检测结果呢?用调试的办法,打开调试界面后,将Time变量添加到Watch一栏中。然后全速运行程序,既可以看到Time中保存变量的变化情况,其中TimeWidthAvrage就是最终的结果。

deae81be-3fbe-11ec-9195-dac502259ad0.png

可以看到TimeWidthAvrage的值等于0x119B8,十进制数对应72120,滴答定时器的一个滴答为1/72M(s),所以Delay_us(1000)的执行时间就是72120*1/72M (s) = 0.001001s,也就是1ms。验证成功。

备注:定时器方法输出检测结果有待改善,你可以把得到的TimeWidthAvrage转换成时间(以us、ms、s)为单位,然后通过串口打印出来,不过这部分工作对于经常使用调试的人员来说也可有可无。相关推荐:学习STM32单片机,绕不开的串口

两种方法对比

软件测试方法

操作起来复杂,由于在原代码基础上增加了测试代码,可能会影响到原代码的工作,测试可靠性相对较低。由于使用32位的变量保存systick的计数次数,计时的最大长度可以达到2^32/72M = 59.65 s。

示波器方法

操作简单,在原代码基础上几乎没有增加代码,测试可靠性很高。由于示波器的显示能力有限,超过1s以上的程序段,计时效果不是很理想。但是,通常的单片机程序实时性要求很高,一般不会出现程序段时间超过秒级的情况。

编辑:jq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6037

    文章

    44562

    浏览量

    635914
  • 示波器
    +关注

    关注

    113

    文章

    6259

    浏览量

    185156
  • 函数
    +关注

    关注

    3

    文章

    4333

    浏览量

    62696
  • GPIO
    +关注

    关注

    16

    文章

    1205

    浏览量

    52148

原文标题:获取STM32代码运行时间的技巧

文章出处:【微信号:c-stm32,微信公众号:STM32嵌入式开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    ups主机选购方法,选择电池运行时间满足

    时,应考虑以下几个因素:能力确定要连接到UPS的设备的电源要求。选择具有足够容量的UPS,以在所需的持续时间内处理负载。电池运行时间考虑在停电期间需要UPS供电多长时间
    的头像 发表于 12-06 09:28 134次阅读
    ups主机选购方法,选择电池<b class='flag-5'>运行时间</b>满足

    影响逆变器电池状态的原因,整体运行时间

    逆变器的使用需要了解影响电池性能和整体运行时间的因素。让我们深入探讨最大化电源设置的关键考虑因素。逆变器效率:逆变器的效率至关重要。当逆变器将电池的DC电能转换为交流
    的头像 发表于 10-18 10:41 306次阅读
    影响逆变器电池状态的原因,整体<b class='flag-5'>运行时间</b>

    C2000™MCU的运行时堆栈大小监测

    电子发烧友网站提供《C2000™MCU的运行时堆栈大小监测.pdf》资料免费下载
    发表于 09-11 09:30 0次下载
    C2000™MCU的<b class='flag-5'>运行时</b>堆栈大小监测

    三菱plc累计运行时间怎么编程

    具有重要意义。本文将详细介绍如何使用三菱PLC编程实现累计运行时间的统计功能。 一、概述 累计运行时间是指设备或系统在一定时间内的总运行时间。在工业生产中,对设备的累计
    的头像 发表于 06-20 11:31 2345次阅读

    变频器带动电机运行时发抖的原因及处理方法

    变频器作为现代工业控制领域的重要设备,广泛应用于电机调速控制中。然而,在实际应用中,有时会遇到变频器带动电机运行时产生抖动的问题。这种抖动不仅影响电机的正常运行,还可能对生产效率和设备寿命造成
    的头像 发表于 05-31 14:43 5758次阅读

    如何在运行时从HSM对SWAP UCB进行编程?

    不知道的限制? 我已确认可以通过 HSM 对 DFLASH 和 PFLASH 进行编程。 是否有示例代码说明如何在运行时从 HSM 对 SWAP UCB 进行编程?
    发表于 05-31 06:37

    STM8S在IAR软件仿真Simulator怎么查看运行时间

    STM8S 在IAR软件仿真Simulator怎么查看运行时间?在某些芯片通信时,会要求延时5us,10us,150ms等,这些延时不需要太精确,只要大概就好,但怎么在Simulator仿真里能通过断点查看,即两个断点之间的运行时间呢? 除了通过IO输出外围用仪器测试,能
    发表于 05-09 07:48

    stm32cubeIDE代码运行时间如何查看?

    stm32cubeIDE 代码运行时间,如何查看?就如 keil 调试时候那样,可以测试代码运行时间。但是在
    发表于 04-16 08:10

    STM32L476+ST253993增加freertos,但是代码下进去系统运行时就卡住,为什么?

    我准备在官方的STM32L476+ST253993增加freertos,但是代码下进去系统运行时就卡住,单步调试,系统一直卡在prvCheckTasksWaitingTermination中
    发表于 04-15 07:27

    使用LL库生成STM32H7代码时存在报错是什么原因导致的?

    使用LL库生成STM32H7代码时存在的BUG
    发表于 04-03 07:33

    stm32做https的server ,serverkeychange运行时间10多s怎么优化?

    stm32做https的server ,serverkeychange这一步运行时间10多s,求优化办法
    发表于 03-27 08:03

    使用STM32CubeMX生成的keil文件,在keil中运行时报错的原因?

    在使用STM32CubeMX过程中,生成的keil文件。 file:///C:/Users/Zhanggp/AppData/Local/Temp/ksohtml11808/wps1.jpg在keil 中运行时出现了报错.
    发表于 03-26 07:10

    如何在运行时擦除/编程UCB?

    我有一个项目需要在现场更新 SOTA。 这需要在运行时更新必要的 UCB 值。 我已经看过擦除/编程 PFLASH 和 DFLASH 的示例代码,但我还没有找到任何特定于 UCB 内存的代码。 我
    发表于 01-22 07:18

    变压器空载运行时功率因数很低是什么原因?

    变压器空载运行时功率因数很低是什么原因? 变压器空载运行时功率因数很低的原因有多种可能,以下将逐一介绍这些可能性。 1. 磁化电流造成的功率因数低:当变压器空载运行时,变压器的铁芯需要维持磁通的运动
    的头像 发表于 01-19 13:58 4516次阅读

    vb运行时错误429不能创建对象

    VB运行时错误429表不能创建对象的错误。这个错误可能会发生在使用CreateObject函数或New关键字创建对象时。 这种错误通常发生在以下情况下: 缺少所需的组件或库:创建对象时,需要确保在
    的头像 发表于 01-09 11:07 2376次阅读