利用Keil调试精确实现软件延时

来源:互联网 发布:apache shiro 集群 编辑:程序博客网 时间:2024/04/29 17:34

c51实现软件延时,无非就是利用forwhile多重循环。以前用到延时函数时,都是从网上下载别人写好的延时子程序。延时5ms,400ms,1s,……,这些延时函数的函数名中都清清楚楚地标明了延时的时间,可我一直不知道这些函数是如何编写的,确切地说,是如果根据延时时间来确定循环次数的。如果是纳秒级的延时,可以通过示波器来观察波形,或者反汇编一下,计算一下指令执行时间,但如果延时时间相对较长,示波器便无能为力了。这几天好好看了一下Keil调试,发现Keil的功能实在是太强大了。利用Keil uVersion的调试就可以写出精确的软件延时程序。以下是我的简单小结,文中所有程序都是在Xtal11.0592MHZ下测试。

比如我需要一个400ms的延时,随便写了个两重循环,外层循环5次,内层循环暂且设为5000

void Delay400Ms(void){

       uchar i=5;

       unint j;

       while(i--){

              j=5000;                     //通过keil调试来确定循环次数

              while(j--);

       }

}

main函数中调用Delay400Ms()

void main()

{

       while1{

              P1=0;

              Delay400ms();

              P1=1;

       }

}

进入uVersion的调试状态,按F10进行单步,当黄色箭头指向Delay400ms()这条语句时记下左边窗中Sys>sec的值,如图,是0.00042426。       

                                      

                                                                        1

再按F10,执行完Delay400ms()后,sec值变为0.38858181,此时记录刚才的初值0.00042426,结果0.38815755即说明执行Delay400ms()耗时388.15755ms,由此可见还未达到400ms的延时要求。此时,增加内循环的次数,将j的值增加到6700,再重复上述过程,算得0.40009874,即Delay400ms()程序延时400.09874ms,此时已经符合延时400ms的要求。

除了上述所说的观察sec值来确定延时时间外,还可以从Keil的性能分析窗口中观测到执行Delay400ms()函数的时间。进入调试状态后使用菜单View->Performance Analyzer Window,打开性能分析对话框,进入该对话框后,只有一项unspecified,点鼠标右键,在快捷菜单中选择Setup PA即打开性能分析设置对话框,对于语言程序,该对话框右侧的“Function Symbol”下的列表框给出函数符号,双击某一符号,该符号即出现在Define Performance Analyzer 下的编缉框中,每输入一个符号名字,点击Define 按钮,即将该函数加入其上的分析列表框。对于汇编语言源程序,Function Symbol 下的列表框中不会出现子程序名,可以直接在编缉框中输入子程序名,点击Close 关闭窗口,回到性能分析窗口,此时窗口共有个选项。全速执行程序,可以看到Delay400Ms 后出现一个蓝色指示条,配合上面的标尺可以直观地看出该函数占整个执行时间的比例,点击相应的函数名,可以在该窗口的状态栏看到更详细的数据,如下图:

        

                                      

 

       图2

值得注意的是,用性能分析窗口来观察延时函数的执行时间要求被观察的延时函数中不能再调用其他任何子函数,被测函数只能由C的基本语句组成,否则观测到的时候并不是整个函数的运行时间。

采用上述方法,得到了以下几个延时程序:

/*

延时400毫秒

*/

void Delay400Ms(void){

       uchar i=5;

       unint j;

       while(i--){

              j=6699;

              while(j--);

       }

}

 

/*

延时1

*/

void delay_1_s()

{

       uchar loop=10;

       unint j;

       while(loop--){

              j=8375;

              while(j--);

       }

}

 

/*

延时秒,参数s为需要延时的秒数

*/

void delay_N_s(uchar s)

{            

       while(s--){

              delay_1_s();           

       }

}

 

但是我碰到一个比较奇怪的问题:在实现N秒延时函数中,我不调用delay_1_s()这个延时1秒函数,而用delay_1_s()中的语句来替换delay_1_s(),改后的函数如下:

void delayNs(uchar s)

{

       uchar loop=10;

       unint j;

       while(s--){

              while(loop--){

                     j=8375;

                     while(j--);

              }            

       }

}

这样一改,问题来了,以下是我从性能分析窗口中得到的测试结果:

delayNs(1)   延时1s

delayNs(2)   延时26.5s

delayNs(3)   延时52s

delayNs(4)   延时103s

对照测试结果,我把这短短几行代码仔细看了好几遍,终于发现了问题所在。原来我在最外层的循环体中漏掉了loop=10这条语句,导致最外层while执行第一次循环时,次外层循环10次(loop10),但最外层从第二次循环往后,次外层都循环了255次,因为最外层第一次循环结束后loop=0xff(01,溢出),所以才出现了上述的这些结果。改正后的代码如下:

void delayNs(uchar s)

{

       uchar loop;

       unint j;

       while(s--){

              loop=10;   //注意,不能忘了此句

              while(loop--){

                     j=8375;

                     while(j--);

              }            

       }

}

 

原创粉丝点击