一個24 位的倒計數定時器,計到0 時,將從RELOAD 寄存器中自動重裝載定時初值。只要不把它在SysTick 控制及狀態寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
四個寄存器:
CTRL SysTick 控制和狀態寄存器
LOAD SysTick 自動重裝載除值寄存器
VAL SysTick 當前值寄存器
CALIB SysTick 校准值寄存器
CTRL中的時鍾源選擇:
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
參數可以填:SYSTICK_CLKSOURCE_HCLK 和 SYSTICK_CLKSOURCE_HCLK_DIV8 不分貧或者八分頻
經過ticks個周期 發生一次中斷,(開啟中斷 設置時鍾源 使能SYSTICK 設置了裝載值)
__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 */ }
//用來存放系統時鍾頻率 static u32 fac_us=0; //us延時倍乘數 //初始化延遲函數 //當使用ucos的時候,此函數會初始化ucos的時鍾節拍 //SYSTICK的時鍾固定為AHB時鍾的1/8 //SYSCLK:系統時鍾頻率 void delay_init(u8 SYSCLK) { HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick頻率為HCLK fac_us=SYSCLK; //不論是否使用OS,fac_us都需要使用 } //延時nus //nus為要延時的us數. //注意:nus的值不要大於1000us void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; //tcnt用來存放當前周期數 最后拿來和ticks對比 u32 reload=SysTick->LOAD; //LOAD的值 重載值 達到這個數之后將會重置 ticks=nus*fac_us; //需要的節拍數 told=SysTick->VAL; //剛進入時的計數器值VAL 存進told里 while(1) { tnow=SysTick->VAL; if(tnow!=told) //還沒有被重載的情況 { if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個遞減的計數器就可以了. else tcnt+=reload-tnow+told; //told < tnow 重載后的情況 told=tnow; if(tcnt>=ticks)break; //時間超過/等於要延遲的時間,則退出. } }; } //延時nms //nms:要延時的ms數 void delay_ms(u16 nms) { u32 i; for(i=0;i<nms;i++) delay_us(1000); }
if(tnow!=told){ if(tnow<told)//還沒有被重載的情況{tcnt+=told-tnow;//這里注意一下SYSTICK是一個遞減的計數器就可以了.}else //told < tnow 重載后的情況{tcnt+=reload-tnow+told; }told=tnow;if(tcnt>=ticks)break;//時間超過/等於要延遲的時間,則退出.}