获取STM32代码运行时间的技巧:软件测试方法和示波器方法
单片机与嵌入式 2024-05-20

前言

测试代码的运行时间的两种方法:
  • 使用单片机内部定时器,在待测程序段的开始启动定时器,在待测程序段的结尾关闭定时器。为了测量的准确性,要进行多次测量,并进行平均取值。
  • 借助示波器的方法是:在待测程序段的开始阶段使单片机的一个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的执行时间: 示波器的观察结果:

可见Delay_us(100),执行了大概102us,而Delay_us(1)执行了2.2us。 更改一下main函数的延时参数: 示波器的观察结果:

可见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就是最终的结果。 可以看到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以上的程序段,计时效果不是很理想。但是,通常的单片机程序实时性要求很高,一般不会出现程序段时间超过秒级的情况。


声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • 单片机和芯片的区别对于嵌入式系统设计有何影响?

    单片机的使用非常广泛,可以说,单片机就是一个微型的计算机。为增进大家对单片机的认识,小编在本文中将对51单片机的CPU以及51单片机的内容结构进行详细介绍。如果你对单片机具有兴趣,不妨和小编一起继续往下阅读...

    3小时前
  • 单片机的执行速度是否受到编程语言的影响?

    单片机可以说是一个微型计算机系统,通过单片机,能够创造出很多有意思的小玩意。为增进大家对单片机的认识,本文将对单片机的工作条件以及51单片机和52单片机的区别予以介绍。如果你对单片机具有兴趣,不妨继续往...

    3小时前
  • 单片机的未来特性多样化:如何使用单片机进行物联网开发?

    单片机用户(原始设备制造商)面临着三大挑战:通过特性、性能或价格实现终端产品差异化;通过缩短产品上市时间以补偿在复杂设计上日益增长的投资;力求在不增加成本的前提下达成上述两大目标。这些挑战构成了未来单片...

    3小时前
  • Linux系统内置模块参数的查看

    提问:我想要知道Linux系统中内核内置的模块,以及每个模块有哪些参数。有什么方法可以得到内置模块和设备驱动的列表,以及它们的详细信息呢? 现代Linux内核正在随着时间变化而迅速增长,以支持大量的硬件、文件系 ... 评论:1 分享:0 收藏:4      2015-11-02 08:00      Dan Nanni, geekpi

    3小时前
  • 在 Linux 上安装 screenfetch

    想在屏幕上显示出你的 Linux 发行版的酷炫标志和基本硬件信息吗?不用找了,来试试超赞的 screenfetch 和 linux_logo 工具。 来看看 screenfetch 吧 screenFetch 是一个能够在截屏中显示系统/主题信息的命令行脚本 ... 评论:7 分享:0 收藏:5      2015-11-02 09:52      Vivek Gite, alim0x

    3小时前
  • 单片机的工作原理

    一、单片机内部结构分析我们来思考一个问题,当我们在编程器中把一条指令写进单片机内部,然后取下单片机,单片机就

    3小时前
  • 存储设备SCSI接口标准

    SCSI协议介绍SCSI,全称Small Computer System Interface,即小型计算机接口

    8小时前
  • 详细说说车规级汽车MCU

    控制类芯片主要就是指MCU(Microcontroller Unit),即微控制器,又叫单片机,是把CPU的主频与规格做适当缩减,并将存储器、定时器、A/D转换、时钟、I/O端口及串行通讯等多种功能模块和接口集成在单个芯片上。

    昨天
  • 把GuiLite移植到STM32上

    STM32单片机上流畅运行

    昨天
  • SRAM与DRAM有何不同?一文带你轻松搞懂!

    在半导体存储器的发展中,静态存储器(SRAM)由于其广泛的应用成为其中不可或缺的重要一员。 随

    06-14
  • 描述linux io_uring 性能

    先看看性能io_uring 需要内核版本在5.1 及以上才支持,liburing的编译安装 很简单,直接clo

    06-14
  • 工程师对单片机编程的总结

    ller Unit 的简称,中文叫微控制器,俗称单片机,是把CPU的频率与规格做适当缩减,并将内存、计数器、USB、A/D转换、UART、PLC、DMA等周边接口。

    06-14
下载排行榜
更多
评测报告
更多
EE直播间
更多
广告