1. 程式人生 > >SysTick定時器應用之一——用於延時函式

SysTick定時器應用之一——用於延時函式

SysTick為簡單的向下計數的24位計時器,可以使用處理器時鐘或外部參考時鐘(通常是片上時鐘源)。當不使用OS時,SysTick定時器可以用作簡單的定時器外設,用以產生週期性中斷、延時或者時間測量。

用於延時函式的話比較簡單,SysTick定時器操作存在4個暫存器

SysTick->CTRL

SysTick->LOAD

SysTick->VAL

其中SysTick->CALIB  校準值暫存器,為軟體提供了校準資訊。CMSIS1.2後就不用這個暫存器了。於是查了一下CMSIS的版本號,位於core_cm4.h中。

因此主要就關注3個暫存器

SysTick->CTRL

SysTick->LOAD

SysTick->VAL

首先看delay_init函式

void delay_init(u8 SYSCLK)
{
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
	fac_us=SYSCLK/8;						//不論是否使用OS,fac_us都需要使用
	fac_ms=(u16)fac_us*1000;				//非OS下,代表每個ms需要的systick時鐘數   
}					

 第一個函式SysTick_CLKSourceConfig

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
  /* Check the parameters */
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  {
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
  }
  else
  {
    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  }
}

 就是配置SysTick->CTRL暫存器

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)

可見SysTick->CTRL暫存器第2位置0,即使用外部參考時鐘。

delay_init(168);  //初始化延時函式

則fac_us == 168 / 8== 21,即1us內要有21個節拍,

    fac_ms ==168 / 8 * 1000 ==21000,即1ms內要有21000個節拍

再看delay_us函式

//延時nus
//nus為要延時的us數.	
//注意:nus的值,不要大於798915us(最大值即2^24/
[email protected]
_us=21) 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; //清空計數器 }

 delay_xms函式

//延時nms
//注意nms的範圍
//SysTick->LOAD為24位暫存器,所以,最大延時為:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK單位為Hz,nms單位為ms
//對168M條件下,nms<=798ms 
void delay_xms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;			//時間載入(SysTick->LOAD為24bit)
	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;     		  		//清空計數器	  	    
} 

 delay_ms函式

//延時nms 
//nms:0~65535
void delay_ms(u16 nms)
{	 	 
	u8 repeat=nms/540;						//這裡用540,是考慮到某些客戶可能超頻使用,
						//比如超頻到248M的時候,delay_xms最大隻能延時541ms左右了
	u16 remain=nms%540;
	while(repeat)
	{
		delay_xms(540);
		repeat--;
	}
	if(remain)delay_xms(remain);
} 

 還是比較簡單的(結合昨天看的位操作)。

這幾個函式也就構成了正點原子寫的delay.c的內容~再次感謝正點原子的程式碼和書~