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丨
|