1. 程式人生 > >使用SysTick延時

使用SysTick延時

//使用中斷定時

void SysTick_Init(void)
{
    if (SysTick_Config(SystemCoreClock / 100000)
    {
        while(1);
    }
}


/*
    時鐘頻率是72MHz,T = 1 / (72 * 1000000),
    SystemCoreClock / 100000 = 720.如果想每10us產生一箇中斷,則傳入的引數是720。
        因為時鐘頻率是72M,所以T = 1/(72 * 1000000),所以在systick計數器每計數一次的時間是T,所以想要多少個T,直接在SysTick_Config(uint32_t ticks),中給引數ticks即可。假如想每1us中斷一次,則ticks = 72,即SystemCoreClock / 1000000.**注意在老版本的系統時鐘常數是SystemFrequency。而在以後的版本是SystemCoreClock。移植到ucosii的時候要注意。**
static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); // Reload value impossible SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; // set reload register NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); // set Priority for Cortex-M0 System Interrupts
SysTick->VAL = 0; // Load the SysTick Counter Value SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; // Enable SysTick IRQ and SysTickzz Timer
return (0); // Function successful } #define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos) // SysTick LOAD: RELOAD Mask SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;這句是systick配置函式的重灌值的設定,結合上面可知SysTick_LOAD_RELOAD_Msk這個值和ticks 是為了對RELOAD暫存器的配置。計數的值就是ticks。 因為傳入的ticks是720,即720計數。而時鐘頻率是72MHz,所以每次計數的結果是10us。 */ //中斷服務函式 void SysTick_handler(void) { TimeDelay_Decrement(); } //時鐘每10us中斷一次,進入中斷函式,然後中斷函式呼叫TimeDelay_Decrement()函式。 //其中TimeDelay是全域性變數 void TimingDelay_Decrement(void) { if (TimeDelay != 0x00) { TimeDelay--; } } //延時函式 void Delay_us(_IO u32 nTime) { TimeDelay = nTime; while (TimeDelay != 0); } /************************************************************************************ *在主函式中首先呼叫SysTick_Init()。這個函式作用是配置時鐘初始值,即多久中斷一次。 *Enable SysTick IRQ and SysTick Timer,這是SysTick_Config函式中的註釋。可以看出 *在這個函式最後使能中斷和時間計時器。所以不需要我們單獨配置CTRL暫存器的TICKINT為去使能中斷了。 *TICKINT 型別 RW 復位值 0 描述:當該位是1的時候,SysTick倒數到0的時候產生SysTick異常請求 *,當該位是0 的時候,無動作。也可以通過讀取COUNTFLAG標誌位來確定計數器是否遞減到0。 * *這樣的話,第一種採用中斷延時的方式就搞定啦! ************************************************************************************/ /********************************************************************************** 另外一種更加簡潔的程式設計 *systick的counter從reload值往下減的時候,CTRL暫存器位16:countflag會置1,且讀取該位的值可清零。 *所以我們使用軟體查詢的方式實現延時。 *推薦使用方法。 * ************************************************************************************/ //systick微妙級延時 void SysTick_Delay_Us(_IO uint32_t us) { uint32_t i; SysTick_Config(SystemCoreClock / 1000000) for (i = 0; i < us; ++i) { //當計數器的值減少到0的時候,CTRL暫存器的位16會置1 while (!(SysTick ->CTRL) & (1 << 16)); } //關閉SysTick定時器 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; } //systick毫秒級延時 void SysTick_Delay_Ms(_IO uint32_t ms) { uint32_t i; SysTick_Config(SystemCoreClock / 1000); for(i = 0; i < ms; i++) { //當計數器的值減少到0的時候,CTRL暫存器的位16會置1 //當置1的時候,讀取該位會清零 while (!(SysTick->CTRL) & (1 << 16))); } //關閉SysTick定時器 SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk; } static __INLINE uint32_t SysTick_Config(uint32_t ticks) { if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ SysTick->VAL = 0; /* 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 (0); /* Function successful */ }