STM32 自定義延時函式
阿新 • • 發佈:2019-01-10
在stm32除錯過程中加入一個延時,有兩種方式:一種是純計數方式,另一種是使用系統計數器的方式。
現使用系統計數器產生中斷的方式實現,查閱STM32的程式設計手冊可知,STM32有一個24bit的系統計時器,並有STK_CTRL、STK_LOAD、STK_VAL、STK_CALIB暫存器供讀寫配置。
而CORTEX_M3有提供了一些函式可以供我們呼叫來控制這幾個暫存器。
在編寫延時函式時需要的庫函式:
它將延時計數寫入LOAD暫存器,設定時鐘源為AHB並啟動計數器。/** \brief System Tick Configuration \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. Counter is in free running mode to generate periodic interrupts. \param [in] ticks Number of ticks between two interrupts. \return 0 Function succeeded. \return 1 Function failed. \note When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b> must contain a vendor-specific implementation of this function. */ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ }
如果我們使用的系統時鐘為72MHz,那麼如果ticks的值設定為72,000,000,則完成一個計數週期為1s,那麼如果ticks值為72,000則計數週期為1ms,ticks值為72則計數週期為1us。
在計數器執行的過程中,每次計數都會產生一個系統中斷,如果我們在中斷中進行計數,就可以得到一個“準確”的延時了。
原始碼如下:
volatile unsigned long time_delay; // 延時時間,注意定義為全域性變數,並且要在中斷中做自減
/********************************************************************************************* 函 數 名: delay_ms 實現功能: 延時一定的毫秒數 輸入引數: volatile unsigned long nms: 延時的毫秒數 輸出引數: 無; 返 回 值: 0 傳送成功, 其他 傳送失敗; 說 明: 無; *********************************************************************************************/ void delay_ms(volatile unsigned long nms) { //設定計數器 若失敗則返回1 if (SysTick_Config(SYS_FREQ/1000)) { while (1) { printf("delay_ms init error\n"); } } time_delay=nms;//讀取定時時間 while(time_delay); SysTick->CTRL=0x00; //關閉計數器 SysTick->VAL =0X00; //清空計數器 } /********************************************************************************************* 函 數 名: delay_us 實現功能: 延時一定的微秒數 輸入引數: volatile unsigned long nus: 延時的微秒數 輸出引數: 無; 返 回 值: 0 傳送成功, 其他 傳送失敗; 說 明: 無; *********************************************************************************************/ void delay_us(volatile unsigned long nus) { //設定計數器 若失敗則返回1 if (SysTick_Config(SYS_FREQ/1000000)) { while (1) { printf("delay_us init error\n"); } } time_delay=nus;//讀取定時時間 while(time_delay); SysTick->CTRL=0x00; //關閉計數器 SysTick->VAL =0X00; //清空計數器 } extern __IO unsigned long time_delay; // 延時時間,注意定義為全域性變數,並且要在中斷中做自減 void SysTick_Handler(void) { if(time_delay > 0) { time_delay--; } }
需要注意的是,SysTick_Config()函式的使用需要呼叫core_cm3.h,而單獨包含core_cm3.h則會產生error:#20:identifier"IRQn_Type"isundefined 錯誤,這是因為資料型別RQn_Type是在stm32f10x.h中宣告的,而core_cm3.h並沒有進行包含,所以我們應用程式需要在包含core_cm3.h之前包含stm32f10x.h才可以。