3399 views|3 replies

119

Posts

0

Resources
The OP
 

Tips for getting STM32 code running time [Copy link]

Preface

There are two ways to test the runtime of your code:

1. Use the internal timer of the microcontroller to start the timer at the beginning of the program segment to be tested and turn it off at the end of the program segment to be tested. In order to ensure the accuracy of the measurement, multiple measurements should be performed and the average value should be taken.

2. The method with the help of an oscilloscope is: at the beginning of the program segment to be tested, a GPIO of the microcontroller outputs a high level, and at the end of the program segment to be tested, the GPIO outputs a low level. By using an oscilloscope to check the length of time of the high level, you can know the running time of this code. Obviously, the method with the help of an oscilloscope is simpler.

Example of the oscilloscope method

The Delay_us function is implemented using the STM32 system tick timer:

#include "systick.h"



/* SystemFrequency / 1000 1ms中断一次

* SystemFrequency / 100000 10us中断一次

* SystemFrequency / 1000000 1us中断一次

*/



#define SYSTICKPERIOD 0.000001

#define SYSTICKFREQUENCY (1/SYSTICKPERIOD)



/**

* [url=home.php?mod=space&uid=159083]@brief[/url] 读取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 

* [url=home.php?mod=space&uid=1238002]@arg[/url] 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;

}

Verify the configuration of GPIO (gpio.h, gpio.c) used in Delay_us execution time:

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

}

Check the execution time of Delay_us in the main function:

#include "systick.h"

#include "gpio.h"



/**

* @brief 主函数

* @param 无 

* @retval 无

*/

int main(void)

{ 

GPIO_Config();



/* 配置SysTick定时周期为1us */

SysTick_Init();



for(;;)

{

TX(HIGH);

Delay_us(1);

TX(LOW);

Delay_us(100);

} 

}

Oscilloscope observations:

It can be seen that Delay_us(100) takes about 102us, while Delay_us(1) takes 2.2us.

Change the delay parameters of the main function:

int main(void)

{ 

/* LED 端口初始化 */

GPIO_Config();



/* 配置SysTick定时周期为1us */

SysTick_Init();



for(;;)

{

TX(HIGH);

Delay_us(10);

TX(LOW);

Delay_us(100);

} 

}

Oscilloscope observations:

It can be seen that Delay_us(100) takes about 101us, while Delay_us(10) takes 11.4us.

Conclusion: This delay function is basically reliable.

Example of using the timer method

Delay_us function is implemented using STM32 timer 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);

}

Check the execution time of Delay_us in the main function:

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

} 

}

How to view the test results? Use the debugging method. After opening the debugging interface, add the Time variable to the Watch column. Then run the program at full speed, and you can see the changes of the variables saved in Time. TimeWidthAvrage is the final result.

It can be seen that the value of TimeWidthAvrage is equal to 0x119B8, which corresponds to 72120 in decimal. One tick of the tick timer is 1/72M (s), so the execution time of Delay_us (1000) is 72120*1/72M (s) = 0.001001s, which is 1ms. Verification is successful.

Note: The timer method outputs the test results to be improved. You can convert the obtained TimeWidthAvrage into time (in us, ms, s) and then print it out through the serial port. However, this part of the work is optional for people who often use debugging.

Comparison of the two methods

Software Testing Methods

The operation is complicated. Since the test code is added on the basis of the original code, it may affect the work of the original code, and the test reliability is relatively low. Since a 32-bit variable is used to save the number of systick counts, the maximum length of the timing can reach 2^32/72M = 59.65 s.

Oscilloscope Method

The operation is simple, and almost no code is added to the original code, and the test reliability is very high. Due to the limited display capability of the oscilloscope, the timing effect is not very ideal for program segments exceeding 1s. However, the real-time requirements of the general single-chip program are very high, and generally the program segment time will not exceed the second level.

丨The article is organized to spread relevant technologies, the copyright belongs to the original author丨

丨If there is any infringement, please contact us to delete丨

This post is from stm32/stm8

Latest reply

The oscilloscope method is easy to operate, requires almost no additional code on the basis of the original code, and has high test reliability.  Details Published on 2021-8-21 12:02
Personal signature

嵌入式、汇编语言等免费视频<

 

2

Posts

0

Resources
2
 
Perfect .
This post is from stm32/stm8
 
 

7452

Posts

2

Resources
3
 

The best is still the timer, which is more convenient and more accurate.

This post is from stm32/stm8
 
Personal signature

默认摸鱼,再摸鱼。2022、9、28

 

104

Posts

0

Resources
4
 
The oscilloscope method is easy to operate, requires almost no additional code on the basis of the original code, and has high test reliability.
This post is from stm32/stm8
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Related articles more>>

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list