void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
SysTick->CTRL&=~(1<<2); //SYSTICK使用外部时钟源
fac_us=SYSCLK/8; //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
reload=SYSCLK/8; //每秒钟的计数次数 单位为K
reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
SysTick->CTRL|=1<<1; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次
SysTick->CTRL|=1<<0; //开启SYSTICK
#else
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
#endif}
疑问点1
/延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK 1MHZ = 1000000HZ
//SYSCLK单位为Hz,nms单位为ms 1S = 1000 ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
疑问点2
SysTick->LOAD=(u32)nms*fac_ms; 这个语句显示的是频率,加载到load这个寄存器不会有什么错误吧!
什么都应该基于实践得来的! 想来想去,不如多实践实践。
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
比如·我现在要设置4ms的延时时间!
把上面的公式展开得到 4*sysclk/8*1000 ,这个数字装入LOAD寄存器中去!
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
SysTick->CTRL&=~(1<<2); //SYSTICK使用外部时钟源
fac_us=SYSCLK/8; //不论是否使用OS,fac_us都需要使用
因为这里我们使用的是72mz的频率(SYSCLK为72MHZ) 所以8分频后为9Mhz ,周期为0.9us
接近1us. 即load中的次数每改变一次, 时间改变为0.9us
把上面4ms 需要的次数,乘以周期 8/sysclk ,即得到所需要的时间!
总结: 上面的延时是不准确的,而且还是基于频率 为9MHZ,不具有灵活性!
可用于对时间精度不高的场合!
systick中的细节还是要参考《cm3 权威指南》 中的内容!