使用SysTick延時
阿新 • • 發佈:2018-12-29
//使用中斷定時
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 */
}