Systick系统滴答定时器
一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
四个寄存器:
CTRL SysTick 控制和状态寄存器
LOAD SysTick 自动重装载除值寄存器
VAL SysTick 当前值寄存器
CALIB SysTick 校准值寄存器
CTRL中的时钟源选择:
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
参数可以填:SYSTICK_CLKSOURCE_HCLK 和 SYSTICK_CLKSOURCE_HCLK_DIV8 不分贫或者八分频
经过ticks个周期 发生一次中断,(开启中断 设置时钟源 使能SYSTICK 设置了装载值)
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) { if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); /* Reload value impossible */ } SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ return (0UL); /* Function successful */ }
//用来存放系统时钟频率 static u32 fac_us=0; //us延时倍乘数 //初始化延迟函数 //当使用ucos的时候,此函数会初始化ucos的时钟节拍 //SYSTICK的时钟固定为AHB时钟的1/8 //SYSCLK:系统时钟频率 void delay_init(u8 SYSCLK) { HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK fac_us=SYSCLK; //不论是否使用OS,fac_us都需要使用 } //延时nus //nus为要延时的us数. //注意:nus的值不要大于1000us void delay_us(u32 nus) { u32 ticks; u32 told,tnow,tcnt=0; //tcnt用来存放当前周期数 最后拿来和ticks对比 u32 reload=SysTick->LOAD; //LOAD的值 重载值 达到这个数之后将会重置 ticks=nus*fac_us; //需要的节拍数 told=SysTick->VAL; //刚进入时的计数器值VAL 存进told里 while(1) { tnow=SysTick->VAL; if(tnow!=told) //还没有被重载的情况 { if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了. else tcnt+=reload-tnow+told; //told < tnow 重载后的情况 told=tnow; if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出. } }; } //延时nms //nms:要延时的ms数 void delay_ms(u16 nms) { u32 i; for(i=0;i<nms;i++) delay_us(1000); }
if(tnow!=told){ if(tnow<told)//还没有被重载的情况{tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.}else //told < tnow 重载后的情况{tcnt+=reload-tnow+told; }told=tnow;if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.}