SysTick定时器的基础学习以及手撕代码

一、什么是Systick系统定时器?
CM3 内核的处理器,内部包含了一个 SysTick 定时器,SysTick 是一个 24 位的倒计数定时器,当计数到 0 时,将从RELOAD 寄存器自动重装载定时初值,开始新一轮计数。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息。
有三个函数是用到这个Systick系统定时器的:
void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);
二、四个寄存器控制Systick定时器工作
1.SysTick控制及状态寄存器(地址:0xE000_E010)

位段名称描述
16COUNTFLAG如果Systick计数到0,这个标志就是1,如果直接读取该位,就会将该位为0
2CLKSOURCE如果是外部时钟则为0,内部时钟为1
1TICKINT1为Systick数到0的时候,中断;0为数到0时不产生中断
0ENABLE1为使能Systick定时器
161514210
COUTNFLAGTICKSOURCETICKINTENABLE

代码分析:

#define  SysTick_CTRL_ENABLE                 ((uint32_t)0x00000001)        //控制寄存器第0位为1,默认是使能Systick时钟
#define  SysTick_CTRL_TICKINT                ((uint32_t)0x00000002)        //控制寄存器第1位为1,默认是当systick计数到0的时候,就中断
#define  SysTick_CTRL_CLKSOURCE              ((uint32_t)0x00000004)        //控制寄存器第2位为1,默认是计数时钟来源是内部时钟
#define  SysTick_CTRL_COUNTFLAG              ((uint32_t)0x00010000)       //控制寄存器第16位为1,开始初始计数器当前值初始化为零

注:
【1】COUNTFLAG其实就是是否数到0的一个标志,如果Systick数到了0,就是为1;
【2】CLKSOURCE其实就是时钟来源标志,来源为0的时候,表示外部时钟,来源为1表示的是内部时钟。
【3】TICKINT其实就是Systick数到0时,是否是直接产生中断还是无响应,一般来说,当Systick数到0的时候,是要产生中断的,也就是一般情况下为1,如果不想让它产生响应,就设置为0就可以了。

2.SysTick重装载数值寄存器(地址:0xE000_E014)

位段名称描述
23:0RELOAD当Systick计数到0的时候,就会把RELOAD寄存器中的值重新装载到CURRENT寄存器中

3.SysTick当前数值寄存器(地址:0xE000_E018)

位段名称描述
23:0CURRENT该寄存器存储了当前的Systick计数器的计数数值

4.SysTick校准数值寄存器(地址:0xE000_E01C)
在这里插入图片描述

/*****************  Bit definition for SysTick_CTRL register  *****************/
#define  SysTick_CTRL_ENABLE                 ((uint32_t)0x00000001)        /*!< Counter enable */
#define  SysTick_CTRL_TICKINT                ((uint32_t)0x00000002)        /*!< Counting down to 0 pends the SysTick handler */
#define  SysTick_CTRL_CLKSOURCE              ((uint32_t)0x00000004)        /*!< Clock source */
#define  SysTick_CTRL_COUNTFLAG              ((uint32_t)0x00010000)        /*!< Count Flag */

/*****************  Bit definition for SysTick_LOAD register  *****************/
#define  SysTick_LOAD_RELOAD                 ((uint32_t)0x00FFFFFF)        /*!< Value to load into the SysTick Current Value Register when the counter reaches 0 */

/*****************  Bit definition for SysTick_VAL register  ******************/
#define  SysTick_VAL_CURRENT                 ((uint32_t)0x00FFFFFF)        /*!< Current value at the time the register is accessed */

/*****************  Bit definition for SysTick_CALIB register  ****************/
#define  SysTick_CALIB_TENMS                 ((uint32_t)0x00FFFFFF)        /*!< Reload value to use for 10ms timing */
#define  SysTick_CALIB_SKEW                  ((uint32_t)0x40000000)        /*!< Calibration value is not exactly 10 ms */
#define  SysTick_CALIB_NOREF                 ((uint32_t)0x80000000)        /*!< The reference clock is not provided */

三、手撕代码
1.delay_ms()代码分析

//延时nus
//nus为要延时的us数.
fac_us=SYSCLK/8;//时基,表示每us计数次数,知道就可以了		    								   
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 				//fac_us表示每us计数的次数,LOAD寄存器中装载的是计数该时间需要的总共次数	  		 
	SysTick->VAL=0x00;        				//清空计数器
	SysTick->CTRL=0x01 ;      				//开始倒数,使能ENABLE计数开始 	 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//计数使能且COUNTFLAG标志不为1,也就是没有计数到零,一直循环,当计数到0之后,就可以停止了
	SysTick->CTRL=0x00;      	 			//关闭计数器
	SysTick->VAL =0X00;       				//清空计数器	 
}

思路总结:
获取传入的参数计数时间,计算对应的次数,将其转入LOAD寄存器中,VAL寄存器初始计数值清零,启动CRTL控制寄存器中计数器使能ENABLE,开始计数,当控制寄存器中的COUNTFLAG位为1时表示计数到0了,也就是计数结束了,此时,延时功能完成,处理后事,关闭计数器,计数器当前值清零。
2.delay_us()代码分析

//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为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;       				//清空计数器	  	    
} 

类似delay_us(u32 nus),留个作业,可以自己试着分析一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尔染君子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值