STM32的SysTick定時器與Delay延時函式
阿新 • • 發佈:2018-12-30
1.BB一下
原子哥的Delay延時函式,在沒有使用OS的情況下,沒有使用SysTick中斷,而筆者希望通過該中斷記錄系統時間
- 不使用OS,使用SysTick中斷
- 不使用OS,不使用SysTick中斷
- 使用OS,使用SysTick中斷
2.BB完了,上程式碼
2.1.不使用OS,使用SysTick中斷
#define SYSTICK_INT_MS 500 /* 定義 SysTick 定時器 1/SYSTICK_INT_MS秒中斷一次 */
static u8 fac_us=0;
static u16 fac_ms=0;
static u32 _tickMs = 0;
void SysTick_Handler(void)
{
_tickMs+=2;/*1/SYSTICK_INT_MS=2ms */
}
/* 獲取系統時間 */
u32 get_systemMs(void){
return _tickMs;
}
/*
**************************************************
** desc : 延時函式初始化
** sysClk : 系統時鐘頻率
** note : SysTick的時鐘頻率是系統時鐘頻率的1/8
**************************************************
*/
void delay_init(u8 sysClk ){
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);/* 選擇外部時鐘 */
fac_us=sysClk/8; /* fac_us個時鐘數1us */
reload=sysClk/8;
reload*=1000000/SYSTICK_INT_MS; /* 根據delay_ostickspersec設定溢位時間 */
/* reload為24位暫存器,最大值:16777216,在168M下,約合0.7989s左右 */
fac_ms=1000/SYSTICK_INT_MS; /* 最小延時單位 */
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;/* 開啟SysTick中斷 */
SysTick->LOAD=reload; /* 每1/delay_ostickspersec秒中斷一次 */
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; /* 開啟SYSTICK */
}
/*
***********************************************
** desc : us 延時函式
** nus : 0~204522252(最大值即2^32/fac_us)
***********************************************
*/
void delay_us(u32 nus){
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;
ticks=nus*fac_us; /* 需要的節拍數 */
told=SysTick->VAL; /* 當前 SysTick 計數值 */
while(1){
tnow=SysTick->VAL;
if(tnow!=told){
if(tnow<told)
tcnt+=told-tnow;
else
tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks) /* 時間超過/等於要延遲的時間,則退出.*/
break;
}
};
}
/*
***********************************************
** desc : ms 延時函式
** nus : 0~204522(最大值即2^32/fac_us/1000)
***********************************************
*/
void delay_ms(u32 nms){
delay_us( nms*1000 );
#if 0
u32 time = get_systemMs();
while(1){
if( get_systemMs()-time>nms )
break;
}
#endif
}
2.2.不使用OS,不使用SysTick中斷
static u8 fac_us=0;
static u16 fac_ms=0;
void delay_init(u8 sysClk){
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=sysClk/8;
fac_ms=(u16)fac_us*1000;
}
void delay_us(u32 nus){
u32 temp;
SysTick->LOAD=nus*fac_us;
SysTick->VAL=0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
void delay_xms(u16 nms){
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;
SysTick->VAL =0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
void delay_ms(u32 nms){
u8 repeat=nms/540;
u16 remain=nms%540;
while(repeat)
{
delay_xms(540);
repeat--;
}
if(remain)delay_xms(remain);
}
2.3.使用OS,使用SysTick中斷
static u8 fac_us=0;
static u16 fac_ms=0;
static u32 _tickMs = 0;
void SysTick_Handler(void){
if( OSRunning==TRUE){
OSIntEnter();
OSTimeTick();
OSIntExit();
}
_tickMs+=2;//OS_TICKS_PER_SEC=500
}
u32 get_systemMs(void){
return _tickMs;
}
void delay_init(u8 sysClk){
u32 reload;
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=sysClk/8;
reload=sysClk/8;
reload*=1000000/OS_TICKS_PER_SEC;
fac_ms=1000/OS_TICKS_PER_SEC;
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;
SysTick->LOAD=reload;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
}
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD;
ticks=nus*fac_us;
OSSchedLock();
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
};
OSSchedUnlock();
}
void delay_ms(u16 nms)
{
if(OSRunning==TRUE)
{
if(nms>=fac_ms)
{
OSTimeDly(nms/fac_ms);
}
nms%=fac_ms;
}
delay_us((u32)(nms*1000));
}