本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!前端
在作单片机项目开发的过程当中,在特殊应用中对代码执行的时间有着严格的要求,那么如何准确的测试出每一个函数的的运行速度是多快呢?一般用单片机测试的方法就是经过示波器观察。ios
好比如今要测试使用二分查找法,在数组中查找一个数字须要屡次时间,测试方法为:每运行一次查找算法,就让LED引脚电平翻转一次,而后使用示波器观察LED引脚的波形,大概就能测试出这个算法的执行时间了。算法
测试代码以下:后端
#include "iostm8s103F3.h"
#include "led.h"
#include "find.h"
void sysclkinit( void ) {
CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
}
void main( void ) {
sysclkinit(); //时钟初始化
__asm( "sim" ); //禁止中断
led_init();
__asm( "rim" ); //开启中断
while( 1 )
{
LED = !LED;
val = binary_search( ( int* )volref, 500, 0, sizeof( volref ) / sizeof( volref[0] ) );
}
}
复制代码
binary_search为二分查找法函数,在100个数据的数组中查找数字500是否存在,LED每翻转一次,执行一次函数。而后经过示波器观察LED的波形。数组
能够看到LED引脚的高低电平时间都为164us,说明这个二分查找法查找数字500所用的时候为164us。LED引脚自己的翻转速度小于0.1us,因此LED引脚翻转自己使用的时间在这里能够忽略不计。markdown
这样在单片机中能够经过LED引脚的翻转经过示波器来观察要测试的函数具体执行所占用的时间。app
这样测试积极精确,可是也比较麻烦,每次测试的时候,还必需要经过硬件电路才能测试,那么能不能不用硬件电路,直接经过软件测试呢?方法固然是有的,能够在Windows中在C编译器中经过软件仿真,测试每一个函数执行的时间。ide
这里使用的编译器为 Dev-C++,这个编译器里面能够直接运行单片机中写好的C函数,而后经过系统提供个几个时间函数,就能够准确测试出函数运行时间了。函数
系统提供的能够测试函数有下面几个post
The clock() function returns an approximation of processor time used by the program.
The value returned is the CPU time used so far as a clock_t; to get the number of seconds used, divide byCLOCKS_PER_SEC. If the processor time used is not available or its value cannot be represented, the functionreturns the value (clock_t) -1.
简单而言,就是该程序从启动到函数调用占用CPU的时间。这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数。
函数原型以下:
返回值类型为clock_t,实际上是一个长整形。
调用这个函数的时候,会返回一个CPU当前时间计数值。要测试时间的话,在函数以前前调用一次clock()函数,将当前时间计数值存储起来。而后调用要测试的函数,测试函数结束以后,在调用一次clock()函数,读取当前的时间计数值,而后用这个计数值减去函数执行前的时间计数值,就能够计算出来函数执行所用的时间,这个时间单位默认为ms。
2.GetTickCount()函数
GetTickCount返回(retrieve)从操做系统启动所通过(elapsed)的毫秒数,它的返回值是DWORD,也是一个长整型数。
它的用法和clock()函数基本同样,在函数执行前调用一次GetTickCount()函数,而后执行函数,函数执行完成后再调用一次GetTickCount()函数,而后计算两次测时间差,这个单位也是ms。
在Windows系统中感受ms很短,可是对于单片机来讲ms时间仍是比较长的,好多函数的执行时间远远小于1ms,若是用上面这两种方法测试的话,许多函数的执行时间是测试不出来的。那么就须要使用更高精度的测试函数。
调用这个函数会返回硬件支持的高精度计数器的频率。注意这个返回的是系统的计时器值,不是时间值。上面两个函数返回的是系统的时间值,而这个函数返回的是系统的计数器值,这个计数器的值至关于时间值来讲,精度就高不少了,大多数的精度均可以达到us级。
这个函数在使用前首先要调用QueryPerformanceFrequency()函数获取系统的计数频率,也就是1s钟系统会计数多少次。
而后使用QueryPerformanceCounter()获取在程序运行先后的计数器值,而后用两次计数器值的差除以计数的频率,就能计算出函数执行所使用的时间。
下面开始使用Dev C++软件测试这三种函数。
编写测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
//待测试函数
void fun(void) {
sleep(1);
}
typedef union _LARGE_INTEGER {
struct {
long LowPart ;// 4字节整型数
long HighPart;// 4字节整型数
};
long long QuadPart;// 8字节整型数
} LARGE_INTEGER;
int main(int argc, char *argv[]) {
int i = 0,val = 0;
clock_t startTime,endTime;
int time = 0;
// 方法 1
startTime = clock(); //计时开始
fun(); //调用函数
endTime = clock(); //计时结束
printf(" 1:程序运行时间为: %d ms\r\n\r\n\r\n",(endTime - startTime));
//方法 2
startTime = GetTickCount(); //计时开始
fun(); //调用函数
endTime = GetTickCount(); //计时结束
printf(" 2:程序运行时间为: %d ms\r\n\r\n\r\n",(endTime - startTime));
//方法 3
LARGE_INTEGER secondcount= {0};
LARGE_INTEGER startcount= {0};
LARGE_INTEGER stopcount= {0};
QueryPerformanceFrequency(&secondcount); //获取每秒多少CPU Performance Tick 单位us
printf(" 3:系统计数频率为: %d \r\n",secondcount.QuadPart);
QueryPerformanceCounter(&startcount); //计时开始
fun(); //调用函数
QueryPerformanceCounter(&stopcount); //计时结束
time=( ((stopcount.QuadPart - startcount.QuadPart)*1000*1000)/secondcount.QuadPart);
printf(" 程序运行时间为: %d us\r\n\r\n",time);
system("pause");
return 0;
}
复制代码
运行结果以下
这里的测试函数实际为 sleep(1); 也就是休眠1s钟,而后使用3种方法分别测试函数执行时间。
使用clock()函数测试代码执行时间为1000ms,使用GetTickCount()函数测试代码执行时间为998ms,使用QueryPerformanceCounter()函数测试代码执行时间为999630us,也就是999.63ms。经过QueryPerformanceFrequency()函数读取到系统1s钟的计数次数为2630703次。
经过系统自带的时间函数就能够直接测试每一个函数执行的时间,这样就能够不使用硬件电路,就能够直接对比不一样的函数执行效率了。