下面的代码演示启用 SysTick 的基本程序:; 使能SysTick定时器,并且使能SysTick异常
LDR R0, =0xE000E010 ; 加载STCSR的地址
MOV R1, #0
STR R1, [R0] ; 先停止SysTick,以防意外产生异常请求
LDR R1, =0x3FF ; 让SysTick每1024周期计完一次。因为是从1023数到
; 0,总共数了1024个周期,所以加载值为0x3FF
STR R1, [R0,#4] ; 写入重装载的值
STR R1, [R0,#8] ; 往STCVR中写任意的数,以确保清除COUNTFLAG标志
MOV R1, #0x7 ; 选择FCLK作为时钟源,并使能SysTick及其异常请求
STR R1, [R0] ; 写入数值,开启定时器
在CMSIS库中有定义对应的配置函数:__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
/* Reload value impossible */
IF ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) {
return (1UL);
}
/* set reload register */
SysTick->LOAD = (uint32_t)(ticks - 1UL);
/* set Priority for Systick Interrupt */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
/* Load the SysTick Counter Value */
SysTick->VAL = 0UL;
/* Enable SysTick IRQ and SysTick Timer */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* Function successful */
return (0UL);
}
SysTick可以通过轮询或者中断方式进行操作,使用轮询的程序可以读取SysTick控制和状态寄存器,检查COUNTFLAG,如果该位置位,则表明SysTick计数已减到0。
中断方式延时参考程序:static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void SysTick_Handler(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
int main(void)
{
//systick时钟为HCLK,中断时间间隔1ms
if (SysTick_Config(SystemCoreclock / 1000))
{
while (1);
}
while(1)
{
Delay(200);//200ms
}
}
轮询方式延时参考程序:void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div4); //选择外部时钟HCLK/4
//为系统时钟的1/4,实际上也就是在计算1usSysTick的VAL减的数目
fac_us=SystemCoreClock/4000000;
//代表每个ms需要的systick时钟数,即每毫秒SysTick的VAL减的数目
fac_ms=(u16)fac_us*1000;
}
void delay_ms(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))); //等待时间到达,看CTRL的第16位(COUNTFLAG)是否为1,看STRL的第0位(ENABLE)是否为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
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; //清空计数器
}
SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如时间测量、定时或者闹铃等。
|