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/fac_us@fac_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的内容~再次感谢正点原子的代码和书~