//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init()
{u32 reload;SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择外部时钟 HCLKfac_us=SystemCoreClock/1000000; //不论是否使用OS,fac_us都需要使用reload=SystemCoreClock/1000000; //每秒钟的计数次数 单位为M reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间//reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右 fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延时的最少单位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}
fac_us = 72M/1M //这句话就是计算在 SystemCoreClock 时钟频率下延时 1us 需要多少个 SysTick 时钟周期
reload= 72*1000000/configTICK_RATE_HZ;//72*1S/configTICK_RATE_HZ 72*1000000/configTICK_RATE_HZ
比如系统节拍1MS,即每个RTOS系统节拍1MS需要72*1000个时钟周期,为了确保定时器与系统时钟对应那么装载值必须为每1MS产生一次中断//延时nus
//nus:要延时的us数.
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)
void delay_us(u32 nus)
{ u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的节拍数 told=SysTick->VAL; //刚进入时的计数器值while(1){tnow=SysTick->VAL; if(tnow!=told){ if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.} };
} 比如 delay_us(50),在刚进入 delay_us 的时候先计算好这段延时需要等待的 systick 计数
次数,这里为 50*72(假设系统时钟为 72Mhz,那么 systick 每增加 1,fac_us=SystemCoreClock/1000000;),然后我
们就一直统计 systick 的计数变化,直到这个值变化了 50*72,一旦检测到变化达到或者超
过这个值,就说明延时 50us 时间到了