嵌入式軟件中的延時函數

延時函數是嵌入式軟件開發中必不可少的功能函數,在每個工程里都能找到它的蹤影。雖然看起來不起眼,但在有些時序控制的場合,使用了一點點delay,往往能解決大問題。下面描述一下delay函數的幾種實現。

Image placeholder
管理員 2021-04-01 13:49

1、前言


延時函數是嵌入式軟件開發中必不可少的功能函數,在每個工程里都能找到它的蹤影。雖然看起來不起眼,但在有些時序控制的場合,使用了一點點delay,往往能解決大問題。下面描述一下delay函數的幾種實現。


2、中斷延時實現


?U16?TimingDelay?=?0;
? ? void?delay_Init(void){
? ? ?SysTick_Config(SystemFrequency?/?1000);?//1ms
? ? ?}?
? ? ?void?delay_DelayMs?(?U16?x?//延時的毫秒數?){?
? ? ?TimingDelay?=?x;?
? ? ?while(TimingDelay?!=?0);??
? ? ?}
? ? ?void?SysTick_Handler(void){?
? ? ?if?(TimingDelay?>?0)?
? ? ?{?TimingDelay?--;?}}

較為常用,借助系統滴答時鐘中斷,來實現較為精準的延時,延時精度可以通過設定中斷周期來控制。但是也因為使用了中斷,如出現中斷方面的異常,容易造成while循環死循環,程序崩潰。就更不能在中斷函數里使用。


3、while循環++的方法


#define?COMPUTE_TIMES_1MS?10120
? ?void?delay_DelayMs(?U16?x)?//延時的毫秒數
? {?
? ?u32?n;?
? ?n?=?x*COMPUTE_TIMES_1MS;?
? ?while(n?>?0)?{?n?--;?}
? }


此方法比較靈活,用于不需要很精確延時的場合。我們可以使用一個GPIO輸出電平再用示波器測量的方式盡量準確的獲得COMPUTE_TIMES_1MS的數值。


Gpio_low();
? delay_DelayMs(100);
? Gpio_high();delay_DelayMs(100);
? Gpio_low();


同樣如果需要做非常小的延時,可以做需要次數的cpu指令次數。


void?delay_DelayCpuTimes(?U16?x){?
? ? ? u32?i;?for?(i=0;i小于x;i++){}}


4、使用nop()語句


void?DelayUS(u32?time){?
? ? while(time--)?{?
? ? __NOP();
? ? __NOP();
? ? __NOP();?
? ? __NOP();
? ? __NOP();
? ? __NOP();?
? ? }
? }


一個__nop空指令的時間就是執行一條指令的時間,主頻不一樣,一次__nop的時間也不一樣,可以使用理論計算的算出1us能執行多少次nop,也可以使用示波器測試的方法來測量。


5、操作系統的sleep函數


void?TSK_SleepMs(uint32_t?ms){?
? ? ?vTaskDelay((configTICK_RATE_HZ?*?ms)?/?1000);
? ? ?}


在帶操作系統的程序中(如freerots,ucos等),系統提供了專用的線程sleep函數,用作延時。注意sleep不要用在中斷函數中。


評論0