利用Keil調試精確實現軟件延時

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

              }            

       }

}

 

發佈了22 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章