【学习笔记】浅谈对于SysTick的理解

        最近在移植某LCD屏的驱动时,对源码产生了一些疑问,索性一次性查找齐全资料写一篇笔记备忘。

        代码大致如下:

#include "stm32f4xx_hal.h"
#include "delay.h" 
static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
	SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
	fac_us=SYSCLK/8;	
	fac_ms=(u16)fac_us*1000;
	/*
	对上面的内容进行解释:
		0xfffffffb换算为二进制得11111111111111111111111111111011
		即把SysTick->CTRL的第2位置0
		查看Cortex-M手册为以下内容:
		----------------------------------------------------------------------------------------
			Bits 	Name 		Type	Reset/Value 	Description
			2 		CLKSOURCE 	R/W 	0  				0=External reference clock (STCLK)
														1=Use core clock
		----------------------------------------------------------------------------------------
		即此位置0,使用外部参考时钟,即使用外部晶振作为时钟参考
	*/
	
}								    
//延时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;       //清空计数器	  	    
}   
//延时nus
//nus为要延时的us数.		    								   
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=0x00;       //关闭计数器
	SysTick->VAL =0X00;       //清空计数器	 
}

        这里我对delay_init()中的fac_us=SYSCLK/8;这一句产生了疑问。例程主函数中调用初始化传入的是delay_init(72);明显为72MHz,这里的除8是为什么呢?

        带着这个疑问,我查了Cortex-M内核手册以及参考了网上的一些帖子,算是大致弄明白了。

        首先,SysTick是内核中的一个系统定时器,又名系统嘀嗒定时器,是一个24位的倒数计数器。

        其中几个位的功能如下:

        最值得注意的是,Systick 的信号来源于系统时钟,可选不分频与八分频。以STM32F103举例,不分频时为72MHz,八分频为9MHz。

        在《STM32F10xxx参考手册(中文)》中有以下这一句话:

        看到这里我们大概就明白了 ,fac_us=SYSCLK/8;这一句将72传入得72/8=9,9*(1/9 000 000) = 1us。注意:这里算的是us,且这里的写法并不标准,fac_us=SYSCLK/8这句的完整算法应该是“72 000 000/8 000 000”。总之,SysTick的实际频率应该就为72MHz的八分之一,即9MHz,我们对其进行处理之后得到一个fac_us可以精确进行1us计时的SysTick->LOAD寄存器的系数,当想延时n us时可以SysTick->LOAD=nus*fac_us;进行精确延时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值