SysTick定時器應用之一——用於延時函式
阿新 • • 發佈:2018-12-29
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的內容~再次感謝正點原子的程式碼和書~