SysTick定时器也叫SysTick滴答定时器,它是Cortex-M4内核的一个外设,被嵌入在 NVIC 中。它是一个24 位向下递减的定时器,每计数一次所需时间为1/SYSTICK,SYSTICK是系统定时器时钟,它可以直接取自系统时钟,还可以通过系统时钟8分频后获取。当定时器计数到0时,将从LOAD 寄存器中自动重装定时器初值,重新向下递减计数,如此循环往复。如果开启SysTick中断的话,当定时器计数到0,将产生一个中断信号。因此只要知道计数的次数就可以准确得到它的延时时间。
CTRL是SysTick定时器的控制及状态寄存器。其相应位功能如下:
LOAD是SysTick定时器的重装载数值寄存器。其相应位功能如下:
VAL是SysTick定时器的当前数值寄存器。其相应位功能如下:
CALIB是SysTick定时器的校准数值寄存器。其相应位功能如下:
SysTick定时器的操作可以分为 4 步: (1)设置SysTick定时器的时钟源。 (2)设置SysTick定时器的重装初始值(如果要使用中断的话,就将中断使能打开)。 (3)清零SysTick定时器当前计数器的值。 (4)打开SysTick定时器。
SysTick.h
#ifndef _SysTick_H #define _SysTick_H #include "system.h" void SysTick_Init(u8 SYSCLK); void delay_ms(u16 nms); void delay_us(u32 nus); #endifSysTick.c
#include "SysTick.h" static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数 /******************************************************************************* * 函 数 名 : SysTick_Init * 函数功能 : SysTick初始化,SYSTICK的时钟固定为AHB时钟的1/8 * 输 入 : SYSCLK:系统时钟频率 * 输 出 : 无 *******************************************************************************/ void SysTick_Init(u8 SYSCLK) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us=SYSCLK/8; //SYSCLK的8分频 保存1us所需的计数次数 fac_ms=(u16)fac_us*1000; //每个ms需要的systick时钟数 } /******************************************************************************* * 函 数 名 : delay_us * 函数功能 : us延时, * 输 入 : 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|=0x01 ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~0x01; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } /******************************************************************************* * 函 数 名 : delay_nms * 函数功能 : ms延时, * 输 入 : nms:要延时的ms数 注意:nms的值,SysTick->LOAD为24位寄存器, 不要大于0xffffff*8*1000/SYSCLK 对168M条件下,nms<=798ms * 输 出 : 无 *******************************************************************************/ void delay_nms(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&=~0x01; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } /******************************************************************************* * 函 数 名 : delay_ms * 函数功能 : ms延时, * 输 入 : nms:要延时的ms数 0~65535 * 输 出 : 无 *******************************************************************************/ void delay_ms(u16 nms) { u8 repeat=nms/540; //这里用540,是考虑到某些客户可能超频使用, //比如超频到248M的时候,delay_nms最大只能延时541ms左右了 u16 remain=nms%540; while(repeat) { delay_nms(540); repeat--; } if(remain)delay_nms(remain); }main.c
/******************************************************************************* * 实 验 名 : SysTick系统定时器 * 实验说明 : * 连接方式 : * 注 意 : SysTick驱动程序在SysTick.c内 *******************************************************************************/ #include "system.h" #include "SysTick.h" #include "led.h" /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int main() { SysTick_Init(168); LED_Init(); while(1) { led1=0; led2=1; delay_ms(500); //精确延时500ms led1=1; led2=0; delay_ms(500); //精确延时500ms }